Puzzling reshape and push!

I find the following behavior puzzling. Start with:

A = randn(5,5)
x = reshape(A, 25)

At this point, A and x point to the same memory block. Indeed:

x[1] = 1.0
A[1]  # returns 1.0

But now, since x is one-dimensional, I can push! to it:

push!(x, 3)
x[1] = 0.0
A[1] # not zero

The push! decouples x and A, which now point to different blocks in memory.

But this feels like a subtle side-effect. Is this intentional? Why not preserve the guarantee that a reshaped array always points to the original array, and let push! raise an error instead in this situation?

Note that we have:

julia> xvec = rand(4);

julia> xmat = reshape(xvec, 2, 2);

julia> push!(xvec, 1.0)
ERROR: cannot resize array with shared data
Stacktrace:
 [1] _growend! at ./array.jl:811 [inlined]
 [2] push!(::Array{Float64,1}, ::Float64) at ./array.jl:853
 [3] top-level scope at REPL[50]:100:

I am not sure if this is related to who is “owner” of the underlying buffer but it seems kinda odd.

2 Likes

Seems worth opening an issue?

2 Likes

I’m not sure what the issue here would be. I think that the behavior should be consistent, but I’m not sure how. You agree that in my example above push!(x, 3) should raise an error? It seems to me that an error is the consistent thing to do (especially considering @kristoffer.carlsson example).

It seems reasonable to error in both cases to me. It feels like an implementation detail leaking out that push! dealias the arrays.

1 Like

I opened an issue: https://github.com/JuliaLang/julia/issues/33143