Gnimuc
Gnimuc

Reputation: 8566

Strange behavior when modifying array in for-loop

take a look at this example:

julia> VERSION
v"0.4.0-rc1"

julia> foo = [1,2]
2-element Array{Int64,1}:
 1
 2

julia> baz = Array(Any,3)
3-element Array{Any,1}:
 #undef
 #undef
 #undef

julia> for i = 1:3
           foo[1] = -foo[1]
           baz[i] = foo
           println("loop",i)
           println("foo: ",typeof(foo),"->",foo)
           println("baz[",i,"]: ",typeof(baz[i]), "->", baz[i])
           println("baz: ",typeof(baz),"->",baz)
       end

loop1
foo: Array{Int64,1}->[-1,2]
baz[1]: Array{Int64,1}->[-1,2]
baz: Array{Any,1}->Any[[-1,2],#undef,#undef]
loop2
foo: Array{Int64,1}->[1,2]
baz[2]: Array{Int64,1}->[1,2]
baz: Array{Any,1}->Any[[1,2],[1,2],#undef]
loop3
foo: Array{Int64,1}->[-1,2]
baz[3]: Array{Int64,1}->[-1,2]
baz: Array{Any,1}->Any[[-1,2],[-1,2],[-1,2]]

the results are unexpected to me, i think baz should be Any[[-1,2],[1,2],[-1,2]].

However, if foo is not an array, the results are reasonable.

julia> foo = 1
1

julia> baz = Array(Any,3)
3-element Array{Any,1}:
 #undef
 #undef
 #undef

julia> for i = 1:3
           foo = -foo
           baz[i] = foo
           println("loop",i)
           println("foo: ",typeof(foo),"->",foo)
           println("baz[",i,"]: ",typeof(baz[i]), "->", baz[i])
           println("baz: ",typeof(baz),"->",baz)
       end
loop1
foo: Int64->-1
baz[1]: Int64->-1
baz: Array{Any,1}->Any[-1,#undef,#undef]
loop2
foo: Int64->1
baz[2]: Int64->1
baz: Array{Any,1}->Any[-1,1,#undef]
loop3
foo: Int64->-1
baz[3]: Int64->-1
baz: Array{Any,1}->Any[-1,1,-1]

my question is what happened here, what's the correct way to assign array in for-loop?

EDIT: i added baz = deepcopy(baz) and everything goes fine. still want to know the reason.

Upvotes: 3

Views: 124

Answers (2)

David P. Sanders
David P. Sanders

Reputation: 5325

This is a common trap, that arises becauses the array foo is a binding. John Myles White has written a very nice blog post on this: http://www.johnmyleswhite.com/notebook/2014/09/06/values-vs-bindings-the-map-is-not-the-territory/

By the way, you should try to avoid Any arrays, which are slow. You can do this easily as follows:

Array(typeof(v), 3)

or just put the explicit type of v, e.g.

Array(Vector{Int}, 3)

Here, Vector{Int} is equivalent to (another name for) Array{Int, 1}.

Also note that instead of all those printlns, you can just use the nice @show:

julia> a = 3
3

julia> @show a
a = 3
3

@show also returns the value shown. On previous versions of Julia, the output looked like a => 3

Upvotes: 4

Reza Afzalan
Reza Afzalan

Reputation: 5746

Julia has Noteworthy Differences from other Languages e.g. unlike MATLAB Julia arrays are assigned by reference. A reference is an alias, or an alternate name to an existing variable. For example, suppose you make peter a reference (alias) to paul, you can refer to the person as either peter or paul. After baz[i] = foo, changing elements of foo will modify baz[i] as well.

Upvotes: 4

Related Questions