Hello! I have some code like this:
type
Affine2* = object
data: array[2, array[3, float]]
proc product*(l: Affine2, r: Affine2): Affine2 =
Affine2(data: [
[
l.data[0][0] * r.data[0][0] + l.data[0][1] * r.data[1][0],
l.data[0][0] * r.data[0][1] + l.data[0][1] * r.data[1][1],
l.data[0][0] * r.data[0][2] + l.data[0][1] * r.data[1][2] + l.data[0][2]
],
[
l.data[1][0] * r.data[0][0] + l.data[1][1] * r.data[1][0],
l.data[1][0] * r.data[0][1] + l.data[1][1] * r.data[1][1],
l.data[1][0] * r.data[0][2] + l.data[1][1] * r.data[1][2] + l.data[1][2]
]
])
As you can see, it's pretty ugly, and I'd really like to simplify it by replacing every instance of r.data[a][b] with something like m[a][b] etc. However, let m = r.data seems to copy the entire thing, while let m = addr r.data doesn't work at all, because it wants a var. Is there any way to accomplish what I want (efficiently) without changing the proc signature?Sure thing!
You can declare a local template inside your proc.
type
Affine2* = object
data: array[2, array[3, float]]
proc product*(l: Affine2, r: Affine2): Affine2 =
template m: untyped = l.data
template n: untyped = r.data
Affine2(data: [
[
m[0][0] * n[0][0] + m[0][1] * n[1][0],
m[0][0] * n[0][1] + m[0][1] * n[1][1],
m[0][0] * n[0][2] + m[0][1] * n[1][2] + m[0][2]
],
[
m[1][0] * n[0][0] + m[1][1] * n[1][0],
m[1][0] * n[0][1] + m[1][1] * n[1][1],
m[1][0] * n[0][2] + m[1][1] * n[1][2] + m[1][2]
]
])
I am not sure about more complicated things, like alignment...
As for the general use case, your biggest risk is probably the GC. I see that you use a stack object as opposed to a garbage-collected ref object, but it is important to make sure that the C code immediately copies a value out if the object were ever to contain ref s.
So my first inclination is that it is safe if you as the programmer ensure that there will be no dangling references. I hope someone else can provide a more technical answer, lol.
Wow, you're right. It should be!
I'm guessing the reason is that it's part of the stdlib, not the "language". Really, though, it is a magical proc, and is implemented by the compiler, so it's not an excuse. Maybe someone with a bit of experience (or write access to the repo :) ) can add it.