Inconsistent behavior with double indexing?

Consider objects a and b, which are array of arrays defined below. These objects are equal according to Julia and the only difference is in how I create them. But double-indexing works very differently on each.

julia> a=fill([3,4],2)
2-element Array{Array{Int64,1},1}:
 [3, 4]
 [3, 4]

julia> b=[[3,4],[3,4]]
2-element Array{Array{Int64,1},1}:
 [3, 4]
 [3, 4]

julia> a==b
true

julia> a[1][1]=5
5

julia> a
2-element Array{Array{Int64,1},1}:
 [5, 4]
 [5, 4]

julia> b[1][1]=5
5

julia> b
2-element Array{Array{Int64,1},1}:
 [5, 4]
 [3, 4]

Can anyone explain (1) why a and b behave differently or (2) how I can modify my code to have it always behave like b, which seems like the intuitively correct result?

The issue is not with indexing but at the creation of a : when you use fill([3,4],2), both elements of a point to the same object in memory (here a vector of value [3,4]). You can check that a[1]===a[2] (note the triple = ) whereas b[1] !=== b[2]. Which means that modifying this object will be reflected in all its occurrences.

EDIT : You can completely change a[1] with a[1]=[5,4] (it will not mutate the old a[1] but create a new element that is not linked to “old” a[1] and a[2] (that will be preserved). But I’m not sure it is easy to do otherwise.

4 Likes

Thanks for explaining why this is happening.

My overall goal was to create an array with placeholder NaN values using fill, then use a for loop to replace each entry. This would need a fill function that creates copies instead of references (I’m not sure how to accomplish this but it may involve the deepcopy function).

Some other things that might work: adding one dimension to the array instead of using an array of arrays (this only works if the sizes are consistent), or push!-ing each new array to build up an array over iterations. These are probably better solutions anyway.

An array comprehension is often a nice way to do this: [[3,4] for _ in 1:2].

2 Likes

See also the somehow related old discussion here …

1 Like