Copying subvector makes pointer?

Hi!
I’m getting some surprising behavior from a Vector of Vectors.

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

julia> pushfirst!(b,b[1])
2-element Array{Array{Int64,1},1}:
 [1, 2, 3]
 [1, 2, 3]

julia> b[1][1]=4
4

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

Why does this happen? This doesn’t happen if I have an array (instead of array of arrays).
I can solve it by using pushfirst!(b,copy(b[1])), but that seems clunky.
I found many tutorials online that state that a=b is a pointer and modifying b will modify a, but that is not the case. Perhaps it was for older versions? Then maybe this is a lingering version of that?
Thanks a lot!

It’s still the case:

julia> x = [1,2,3];

julia> y = x;

julia> x[1] = 42;

julia> y
3-element Array{Int64,1}:
 42
  2
  3

To your original question, scalar indexing, i.e. b[1], (in contrast to slicing, i.e. b[1:2]) generally doesn’t create a copy. That’s why you see the behaviour you see. The “it doesn’t happen if I don’t have an array of arrays” part is due to the fact that the elements b[1] in this case are immutable numbers (in contrast to mutable arrays). Compare this to the example above:

julia> x = 4;

julia> y = x;

julia> x = 42;

julia> y
4
1 Like

You’ve basically answered your own question. b is an array of pointers and you effectively put the same pointer in that array twice. No when you change the memory these pointers point to it affects them both. Copying the memory before you change it is the correct solution.

I see. So Julia is like C, and arrays are always pointers, while scalars behave more normally.
Good to know! Thanks for clarifying!

1 Like

This extract from previous threads helped me (related, but not exactly the same thing): Assignment and mutation · JuliaNotes.jl

3 Likes

They’re not necessarily always pointers - that’s an implementation detail. Types that are isbits for example may be stored inline. Mutability semantics are detached from that notion.

It’s not generally useful to fit pointer logic into julia semantics.

2 Likes