Reputation: 308
I pasted the full MWE below. Since it is a bit long, I first give a break-down.
Task: I have a global vector vec
that is going to be randomly updated in a loop. I have a global vector vecvec
(vector of vectors) that is supposed to store the history of the vec
s.
Attempted Solution (does not work): The function make_vec()
randomly updates vec
. I put this in a loop as follows.
for i in 1:5
make_vec()
println(vec)
push!(vecvec,vec)
end
Running this (or rather the MWE below), one can see from the printed output, that the global variable vec
is updated by make_vec()
in each round of the loop as intended. But:
Question 1: Why then are all vectors in the collected history vecvec
the same?
I can guess an answer to the question, namely that push!
does not push the actual vector vec
but only a reference to vec
. Thus, when I inspect vecvec
after completion of the loop, all entries are identical to the last update of vec
.
But this raises another question.
Question 2: In the MWE below, I add two alternative implementations of make_vec()
. In particular, make_vec2()
(make_vec3()
is similar) is the same as make_vec()
but replaces the for-loop with list comprehension. Why does replacing make_vec()
in the loop by make_vec2()
give a different result (in fact the desired result)?
vec = [1,2,3]
vecvec = []
function make_vec()
for i in 1:3
vec[i] = rand(0:9)
end
end
function make2_vec()
global vec = [rand(0:9) for i=1:3]
end
function make3_vec()
local vec3 = [1,2,3]
for i in 1:3
vec3[i] = rand(0:9)
end
global vec = vec3
end
for i in 1:5
make_vec() # make_vec2 and make_vec3 would give the desired result, but not make_vec
println(vec)
push!(vecvec,vec)
end
print(vecvec)
I run this in a Jupyter notebook with kernel 1.8.3.
Upvotes: 2
Views: 134
Reputation: 69949
In
for i in 1:3
vec[i] = rand(0:9)
end
you do not change the value (array in this case) that vec
is bound to. Instead you only change the elements stored in the array.
This is typically called in-place update.
On the other hand:
global vec = [rand(0:9) for i=1:3]
allocates a new vector and binds this new value to vec
variable. This means that instead of updating values in some container you replace the container.
The same with:
local vec3 = [1,2,3]
for i in 1:3
vec3[i] = rand(0:9)
end
global vec = vec3
The local vec3 = [1,2,3]
allocates new container and global vec = vec3
binds this new container to vec
variable.
Is this clear?
As a side note - it is better do not use vec
as variable name as vec
is a function name that is defined in Base Julia.
Upvotes: 5