I am writing code in Julia which collects some output from a function foo
(which mutates its input argument), and I'm trying to append the recursive evaluations from this function in an array A
.
For instance, foo!(x)
changes the value of x
by adding 1
to each of its elements.
function foo!(x)
x .= x .+ 1
return(x)
end
julia> x = [1, 1];
julia> foo!(x);
julia> x
2-element Array{Int64,1}:
2
2
I want to create an array A
which stores the value of x = f(x)
over a fixed range. However, A
just ends up containing multiple copies of the final value of f(x)
, e.g.,
julia> x = [1, 1];
julia> A = [x];
julia> for i=1:3
push!(A, foo!(x))
end
julia> A
4-element Array{Array{Int64,1},1}:
[4, 4]
[4, 4]
[4, 4]
[4, 4]
I'm trying to get it to get it to efficiently output something similar to
julia> B
4-element Array{Array{Int64,1},1}:
[1, 1]
[2, 2]
[3, 3]
[4, 4]
I haven't been able to find a helpful resources for a developing a solid understanding of mutations, or the order in which mutations are executed in Julia. Any help in this regard would be greatly appreciated!
The way you've written it, you repeatedly push!
the same object into A
, which your foo!
function mutates:
julia> x = [1, 1]
2-element Vector{Int64}:
1
1
julia> A = [x]
1-element Vector{Vector{Int64}}:
[1, 1]
julia> foo!(x)
2-element Vector{Int64}:
2
2
julia> A
1-element Vector{Vector{Int64}}:
[2, 2]
One way of fixing this is to copy
the elements in A
before x
gets mutated:
julia> for i ∈ 1:3
A[i] = copy(x)
push!(A, foo!(x))
end
julia> A
4-element Vector{Vector{Int64}}:
[1, 1]
[2, 2]
[3, 3]
[4, 4]
A classic read on values vs. bindings can be found here.