Difference between element-wise allocation and copy()

Hi!

I was using the elemet-wize allocation ( .= ) as the copy function. But I found that in certain cases, it’s not. I want to know in which case I can use element-wize allocation as the copy function.

for example

C11 = fill(0.0im,(2,10))
C12 = fill(0.0im,(2,10))
for i = 1: 2
    C13 = fill(i,10)
    C11[i,:,:] = copy(C13)
    C12[i,:,:] .= 1*C13
end
C12[1,:]  # ten of 1.0
C12[2,:]  # ten of 2.0
C11[1,:]  # ten of 1.0
C12[2,:]  # ten of 2.0

C15 = fill(1.0im*fill(0.0,(10)),(2))
C14 = fill(1.0im*fill(0.0,(10)),(2))
for i = 1: 2
    C13 = fill(i,10)
    C14[i] = copy(C13)
    C15[i] .= 1*C13
end
C14[1] # ten of 1.0
C14[2] # ten of 2.0
**C15[1] # ten of 2.0**
C15[2] # ten of 2.0

I found strange results

C14 = fill(1.0im*fill(0.0,(10)),(2))
for i = 1: 2
    C13 = fill(i,10)
    C15[i] **.=** C13
end
C15[1] # 2.0
for i = 1: 2
    C13 = fill(i,10)
    C15[i] **=** C13
end
C15[1] #1.0
for i = 1: 2
    C13 = fill(i,10)
    C15[i] **.=** C13
end
C15[1] # 1.0

You are having a fill array-of-arrays problem. Hint: do C15[1][1] = 1 and then look at C15[2].

TDLR: You are initializing your arrays so that every element “points” to the same array, so that mutating one element’s array mutates them all.

This is compounding your fill confusion with assignment vs. mutation confusion.

TLDR: = copy assigns that element to a new array, without affecting the other elements, whereas .= mutates the existing array (which affects all your other elements due to the fill confusion).

2 Likes

I’ve often wanted a package that could take code like this:

a = fill([3,1,4], 4)

and draw a diagram like this:
image

as opposed to

b = [[3,1,4] for i=1:4]

for which it would draw:
image

9 Likes