mbauman
mbauman

Reputation: 31342

Why isn't dot-assignment updating multiple arrays?

I want to assign some computation into a pair of arrays, with the top portion going into array x, and the bottom portion going into y. I attempted the following, but neither x nor y were updated:

x = zeros(2)
y = zeros(3)
[x;y] .= [1.2, 4.5, 2.3, 4.5, 5.6]

Upvotes: 3

Views: 158

Answers (1)

mbauman
mbauman

Reputation: 31342

In general1, the .= operator just assigns into whatever the result of the left hand side evaluates to — and in this case the result is a brand new array with the contents of x and y vertically concatenated. You can see that [x; y] creates a new array decoupled from x and y by just trying it by itself:

x = zeros(2)
y = zeros(3)
r = [x;y]
r[1] = 1

julia> r
5-element Array{Float64,1}:
 1.0
 0.0
 0.0
 0.0
 0.0

julia> x
2-element Array{Float64,1}:
 0.0
 0.0

julia> y
3-element Array{Float64,1}:
 0.0
 0.0
 0.0

julia> r .= [1.2, 4.5, 2.3, 4.5, 5.6] # just changes `r`, not `x` or `y`
5-element Array{Float64,1}:
 1.2
 4.5
 2.3
 4.5
 5.6

julia> all(iszero, x) && all(iszero, y)
true

Now, you can update x and y if they're put into a special "lazy" container from LazyArrays.jl that emulates a concatenation operation:

julia> using LazyArrays

julia> ApplyArray(vcat, x, y) .= [1.2, 4.5, 2.3, 4.5, 5.6]
5-element ApplyArray{Float64,1,typeof(vcat),Tuple{Array{Float64,1},Array{Float64,1}}}:
 1.2
 4.5
 2.3
 4.5
 5.6

julia> x
2-element Array{Float64,1}:
 1.2
 4.5

julia> y
3-element Array{Float64,1}:
 2.3
 4.5
 5.6

1 There's one important exception to this general rule: we support indexed assignment with multiple selected indices in combination with .= to update the original array. In other words, the syntax y[1:2] .= [3.4, 5.6] will indeed update the first two elements of y, even though y[1:2] elsewhere will allocate a brand new 2-element array decoupled from y. In other words, when you use indexing on the left-hand side of .=, it automatically uses a view when necessary.

Upvotes: 5

Related Questions