Assignment to multiple targets - how does it work?

Given:

``````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")
Stacktrace:
[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
10

julia> d
20
``````

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?

Also:

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

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

julia> (b,)
(20,)
``````

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,)
(60,)

``````

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.

NB:
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.