Subtle differences between assignment and mutation in Julia as shown in the script below are easy to be missed or misunderstood by a beginner like me. I’m starting to understand and realize the importance, but still not really confident. If there’s a good (clear, plain, accurate and concise) document on the issue for beginners, I really appreciate a pointer to it.
In the script below, temp(a) has an assignment, and temp1(a) a mutation. The difference is just a dot, and the results look the same [4,5,6]. It’s hard for a beginner to realize they are actually different arrays. Interestingly, temp1(a) allocates more than six times of memory than temp(a) and slower (true when @benchmark is used).
temp2(a) is same as temp1(a) except it returns nothing. It has smaller allocation and faster execution than the other two functions.
I was naively using functions like temp(a), but realize that I should use functions like temp2(a) as temp!(a) when I mean mutation of the array a. Is this thinking correct?
a = [1,2,3];
function temp(a)
a = [4,5,6]
end
function temp1(a)
a .= [4,5,6]
end
function temp2(a)
a .= [4,5,6]
return nothing
end
temp2 (generic function with 1 method)
@time a1 = temp(a)
0.007462 seconds (3.14 k allocations: 163.691 KiB)
3-element Array{Int64,1}:
4
5
6
@time a2 = temp1(a)
0.056520 seconds (20.21 k allocations: 1.006 MiB)
3-element Array{Int64,1}:
4
5
6
a == a1 == a2
true
a === a1
false
a === a2
true
a = [1,2,3]
3-element Array{Int64,1}:
1
2
3
@time temp2(a)
0.005079 seconds (217 allocations: 12.904 KiB)
a
3-element Array{Int64,1}:
4
5
6