Reputation: 2589
I'm a bit puzzled about the way that Julia 1.0.3 treats global variables. Is there a way to use !push to update a global array?
While playing in the REPL, I want to update a global variable, then push!
the result to a global array to store it.
var = [1]
res = []
for i in 1:5
global var
global res
push!(var,i)
print(string(var,"\n"))
push!(res,var)
end
However, the values stored in res
are as follows:
[1, 1, 2, 3, 4, 5]
[1, 1, 2, 3, 4, 5]
[1, 1, 2, 3, 4, 5]
[1, 1, 2, 3, 4, 5]
[1, 1, 2, 3, 4, 5]
Whereas I would expect this:
[1, 1]
[1, 1, 2]
[1, 1, 2, 3]
[1, 1, 2, 3, 4]
[1, 1, 2, 3, 4, 5]
Particularly puzzling since behaviour seems as expected with variables, instead of arrays:
var = 1
res = []
for i in 1:5
global var
global res
var = var + i
print(string(var,"\n"))
push!(res, var)
end
Which gives expected result:
2
4
7
11
16
I am clearly missing something.
Upvotes: 0
Views: 976
Reputation: 31342
You're pushing the same var
array to every spot in the res
array. For example:
julia> var = [1]
1-element Array{Int64,1}:
1
julia> res = [var, var]
2-element Array{Array{Int64,1},1}:
[1]
[1]
julia> var[1] = 2
2
julia> res
2-element Array{Array{Int64,1},1}:
[2]
[2]
Both elements in the res
array are var
itself. So if you modify var
(with push!
or indexed assignment or somesuch), then no matter how you access it you'll see those modifications.
This doesn't occur with numbers because you cannot modify numbers themselves. You can change which number is stored in an array, but you cannot change the number 1
to represent 2
everywhere that 1
had previously been used — that's the equivalent of what's happening here.
To fix this, you'll often want to just create your var
array inside the for loop (instead of outside it). But in this case, since you're iteratively adding things to var
and want to save that intermediate state, you can use copy
:
julia> for i in 1:5
global var
global res
push!(var,i)
print(string(var,"\n"))
push!(res,copy(var))
end
Any[1]
Any[1, 2]
Any[1, 2, 3]
Any[1, 2, 3, 4]
Any[1, 2, 3, 4, 5]
julia> res
5-element Array{Any,1}:
Any[1]
Any[1, 2]
Any[1, 2, 3]
Any[1, 2, 3, 4]
Any[1, 2, 3, 4, 5]
Upvotes: 2