Assignment to multiple targets - how does it work?


julia> a = zeros(5); b = zeros(5); R = collect(10:10:100);

This naturally fails:

julia> a[1:end] = R
ERROR: DimensionMismatch("tried to assign 10 elements to 5 destinations")
 [1] throw_setindex_mismatch(::Array{Float64,1}, ::Tuple{Int64}) at .\indices.jl:92
 [2] setindex_shape_check(::Array{Float64,1}, ::Int64) at .\indices.jl:143
 [3] setindex!(::Array{Float64,1}, ::Array{Float64,1}, ::UnitRange{Int64}) at .\array.jl:618

But then this succeeds:

julia> c, d = R;

julia> c

julia> d

Why doesn’t this fail with a “tried to assign 10 elements to 2 destinations” error? Why does Julia silently discard the rest of the values in such cases?


julia> a[1:end],b = R;

julia> (a,)
([10.0, 10.0, 10.0, 10.0, 10.0],)

julia> (b,)

This is seen as a broadcast of R’s first value into a (and gives an appropriate warning in 0.7), whereas:

julia> m, n, o, p, q, b = R;

julia> (m, n, o, p, q)
(10, 20, 30, 40, 50)

julia> (b,)

distributes R’s values over the variables.

What will be the semantics of the previous a[1:end],b = R; assignment after the deprecation is removed?

And is there an easy way to get the effect of a[1], a[2], a[3], a[4], a[5], b = R; with more compact and more generalizable code?

1 Like

There are two things going on here.

First, multiple return values are destructured. Whenever you have a comma-separated list of variable names on the left hand side of a =, that is treated as a tuple and the iterable on the right hand side is assigned elementwise. Extra values are not.

The other expression is an invocation of setindex!, eg

julia> Meta.lower(Base, :(a[1:end] = R))
:($(Expr(:thunk, CodeInfo(
 1 ─ %1 = Base.lastindex(:a)::Any                                                                                                                                            │
 │   %2 = :(:)(1, %1)::Any                                                                                                                                                   │
 │        Base.setindex!(:a, :R, %2)                                                                                                                                         │
 └──      return :R                                                                                                                                                          │

setindex! checks for conforming sizes, hence the DimensionMismatch.

1 Like

We often find broken links in old posts like the one above. This should probably be pointing to the manual here.

Could the admins automatically flag all broken links to the respective post authors?

Personally, I would prefer not to be notified or pinged about broken links in posts I made years ago.

Broken links are an inevitable part of the web. Readers can just use search engines to figure out the current URL.