I guess the dot in front of the equal sign is a typo?
No, it is correct, and required to make the operation work in-place.
Ok, this notation is not easy to understand for a beginner. Here my code snippet to understand better:
array = [1 2.0 3.3; 2.0 7.0 -1.3]; array_A = copy(array)
array_A .= clamp.(array_A, -1.0, 6.0)
array_B = clamp.(array, -1.0, 6.0)
array_C .= clamp.(array, -1.0, 6.0) # ERROR: UndefVarError: array_C not defined
When you write x[1] = 1
or y[:] = [1,2,3]
, you depend on x
and y
already being defined as arrays and you’re simply mutating their stored values.
Writing z .= [1,2,3]
is similar. It looks deceptively similar to z = [1,2,3]
, but they’re two different things: the former updates the stored values in-place, while the latter (re)assigns the identifier entirely.
@uniment And I guess the in-place
operation saves time and memory for large arrays?
Small arrays too
If you struggle with the dots, I often prefer the equivalent map
and map!
which can make the in-place intent a little more explicit.
In this case, it would be written as:
map!(array, array) do x
clamp(x, lo, hi)
end
In fact, if the array in question is one where the first axis is much smaller than the trailing ones, such as a wide matrix with a handful of rows, then in-place broadcasting can be much slower than map!
Except for DataFrames (see What if `df.col .= v` was in-place?)