Hi,
I am buffled by what copy!(z,view(x,1,:)') does. Seems off. Example:

x = [11 12;111 112] #to read from
y = [ones(1,2)*1,ones(1,2)*2] #2-vector of matrices, to be pushed to
z = zeros(1,2) #preallocate z
copy!(z,view(x,1,:)') #copy first row of x to z
display(z)
pushfirst!(y,z)
copy!(z,view(x,2,:)') #copy 2nd row
display(z)
pushfirst!(y,z)
display(y)

Looks like mutation semantics to me. You donâ€™t reassign z in the given example, just mutate its preallocated instance. y gets the same instance assigned to z pushed to its beginning twice, in short y[1] === y[2]. If you want to see different values, you do need to allocate more.

Yes, the whole idea was to (keep) mutating an existing array, so as to avoid allocations in a long loop. Still, the display(z) (twice in the example) suggests that z is changed. Itâ€™s just at the stage of pushfirst!() that it somehow isnâ€™t.

When you pushfirst!(y, z), youâ€™re putting the matrix named z inside y. If you do it twice, y will contain [#= the matrix named z =#, #= the matrix named z =#, ...]. If you mutate the matrix named z, then that matrix changes. And since y has that matrix placed in two locations, youâ€™ll see that change in both those locations. Because itâ€™s just one matrix.

If you decide to do z = x[1,:]' in between, youâ€™re deciding to repurpose the name z for a brand spanking new matrix â€” and that matrix will be completely independent from anything you might have called z in the past.

To possibly further clarify what @Benny and in the mean time also @mbauman are saying, the variable z just points to some location in memory. When you mutate z using copy! (or some .=-like operation), z still points to the same location, but the values in memory have now changed.

julia> z = ones(1, 2)
1Ă—2 Matrix{Float64}:
1.0 1.0
julia> pointer(z) # Memory location where z points to
Ptr{Float64} @0x000002245d8f0900
julia> z .*= 2
1Ă—2 Matrix{Float64}:
2.0 2.0
julia> pointer(z) # Same location (but different values in memory)
Ptr{Float64} @0x000002245d8f0900
julia> z = [2. 2.] # New variable coincidentally also called z, with the same values as before
1Ă—2 Matrix{Float64}:
2.0 2.0
julia> pointer(z) # but new location
Ptr{Float64} @0x000002245da1c4a0

When you pushfirst!z into y the new first entry of y should be found at the memory location corresponding to z. Mutating z and using pushfirst! again, the first two entries both point to the same location in memory, so have the same values.

If you intend to have 2 different mutable matrices, youâ€™ll need to allocate 2 mutable matrices because itâ€™s the memory-safe way for references to share data, as you inadvertently ran into. If you only need the two, you can preallocate those. If you have a loop with indeterminate iterations, then you have a situation where you need to allocate frequently. Is it possible for the matrices to be immutable? That is far more feasible to store directly in y instead of a separate allocation, though youâ€™ll probably want to preallocate elements for y because resizing needs allocation.

Thanks, Iâ€™ll follow your idea and probably set up multidimensional array y and change elements in that. (I was probably trying to be too clever with my vector of matricesâ€¦)