# Destructuring & setindex!

**URL:** <https://discourse.julialang.org/t/destructuring-setindex/25475>\
**Category:** Internals & Design\
**Tags:** question\
**Created:** [June 20, 2019, 8:06am UTC](https://discourse.julialang.org/t/destructuring-setindex/25475 "2019-06-20T08:06:21Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [June 20, 2019, 8:06am UTC](https://discourse.julialang.org/t/destructuring-setindex/25475/1 "2019-06-20T08:06:21Z")

</div>

[Tuple destructuring](https://docs.julialang.org/en/v1/manual/functions/#Multiple-Return-Values-1) works even if the variables on the LHS are `x[i...]` expressions, eg

```julia
g(y) = y, 2 * y

function foo!(x1, x2, y)
    for i in eachindex(y)
        x1[i], x2[i] = g(y[i])
    end
    x1, x2
end

x1 = zeros(3)
x2 = zeros(3)
foo!(x1, x2, 1:3)

```

as opposed to writing out

```julia
function foo!(x1, x2, y)
    for i in eachindex(y)
        z = g(y[i])
        x1[i] = z[1]
        x2[i] = z[2]
    end
    x1, x2
end

```

but I am wondering where this is **documented**. Or does this follow logically from something else?

---

<div class="post-metadata">

**Author:** ![yakir12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yakir12/32/297_2.png) [@yakir12](https://discourse.julialang.org/u/yakir12)\
**Post date:** [June 20, 2019, 8:18am UTC](https://discourse.julialang.org/t/destructuring-setindex/25475/2 "2019-06-20T08:18:55Z")

</div>

I do not know where exactly this is documented, but I often set multiple variables on the LHS with a tuple or even a vector. It’s super neat.

---

<div class="post-metadata">

**Author:** ![Paul\_Soderlind](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paul_soderlind/32/1753_2.png) [@Paul\_Soderlind](https://discourse.julialang.org/u/Paul_Soderlind)\
**Post date:** [July 9, 2019, 11:00am UTC](https://discourse.julialang.org/t/destructuring-setindex/25475/3 "2019-07-09T11:00:26Z")

</div>

It would be great to have this clarified/documented. Maybe submit a PR for the docs?

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [July 9, 2019, 11:18am UTC](https://discourse.julialang.org/t/destructuring-setindex/25475/4 "2019-07-09T11:18:12Z")

</div>

I would prefer to leave this to someone more familiar with lowering, as it appears to be recursive. Eg

```julia
julia> Meta.@lower a[i][j], b[k] = (2, 3)
:($(Expr(:thunk, CodeInfo(
    @ none within `top-level scope'
1 ─ %1 = 2
│ %2 = 3
│ %3 = Base.getindex(a, i)
│ Base.setindex!(%3, %1, j)
│ Base.setindex!(b, %2, k)
│ %6 = Core.tuple(%1, %2)
└── return %6
))))

```

and the exact form is important for macros.

This is one of those features that “just works”, and users don’t even need to think about them, so the documentation is more for understanding the AST and confirming that this is something one can rely on.

---

<div class="post-metadata">

**Author:** ![Paul\_Soderlind](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paul_soderlind/32/1753_2.png) [@Paul\_Soderlind](https://discourse.julialang.org/u/Paul_Soderlind)\
**Post date:** [July 9, 2019, 3:10pm UTC](https://discourse.julialang.org/t/destructuring-setindex/25475/5 "2019-07-09T15:10:29Z")

</div>

> This is one of those features that “just works”.

Right, but it feels risky to use an undocumented feature (maybe it’s a bug…).

My experience with filing a PR for the docs is that the core team takes it as a starting point. If you prefer, I could write up something simple, for instance, by borrowing your example `(a[i][j], b[k]) = (2, 3)`. Maybe that would trigger someone to add details.

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [July 9, 2019, 3:46pm UTC](https://discourse.julialang.org/t/destructuring-setindex/25475/6 "2019-07-09T15:46:02Z")

</div>

I discovered this just a few weeks ago myself when I had an occasion to update two refs at the same time like this. I wasn’t sure if it would do what I wanted so I checked the lowering and was happy to discover that it did.

It’s even recursive into nested tuples.

```julia
julia> Meta.@lower a.x, b[], (c.y, d[]) = (1,2, (3,4))
:($(Expr(:thunk, CodeInfo(
...
│ (Base.setproperty!)(a, :x, %12)
│ (Base.setindex!)(b, %3)
...
│ (Base.setproperty!)(c, :y, %24)
...
│ (Base.setindex!)(d, %28)

```

Even more obliquely, it’s even allowed to define limited functions this way:

```julia
julia> f(), g(), x+y = 1:3
1:3

julia> f()
1

julia> g()
2

julia> 1+1
3

```

Of course, we cannot do anything more interesting than constant-valued functions since the RHS is an immediately-evaluated value and not a function body.

Looking at the lisp, it looks like tuple destructuring is implemented exactly as a loop that generates the same code as a sequence of assignments for each thing on the LHS while iterating over the RHS. And I think it’s something you can count on as it’d be an error otherwise. Let’s document it!

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [July 10, 2019, 4:47am UTC](https://discourse.julialang.org/t/destructuring-setindex/25475/7 "2019-07-10T04:47:03Z")

</div>

> [@Paul\_Soderlind](#):
>
> I could write up something simple

I think it would be best to start with an issue (I could not find one) and ask for guidance there. I can imagine two places for this in the docs:

1. in [multiple return values](https://docs.julialang.org/en/v1/manual/functions/#Multiple-Return-Values-1), explaining this feature to the user, with an example,
2. in the dev docs, documenting the AST and the rules (which appear to be “anything that even remotely makes sense goes”, as @mbauman pointed out).

An issue first would help clarify what of this is intended, and what isn’t. Also, the two points above would not need to be addressed in the same PR — I think I would leave 2. for core devs.

---

<div class="post-metadata">

**Author:** ![c42f](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/c42f/32/52842_2.png) [@c42f](https://discourse.julialang.org/u/c42f)\
**Post date:** [July 10, 2019, 8:14am UTC](https://discourse.julialang.org/t/destructuring-setindex/25475/8 "2019-07-10T08:14:15Z")

</div>

Recently I’ve been writing a [massive pile of tests](https://github.com/JuliaLang/julia/pull/32201) for lowering which can partially serve the need of documenting the intent of lowering without having to refer to the code itself. Not everything is covered yet, but nested destructuring is:

> <https://github.com/JuliaLang/julia/blob/dfe0c8dcc27213574096d6f3d3cdaf81b2aefc7c/test/compiler/lowering.jl#L724-L750>

---

<div class="post-metadata">

**Author:** ![Paul\_Soderlind](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paul_soderlind/32/1753_2.png) [@Paul\_Soderlind](https://discourse.julialang.org/u/Paul_Soderlind)\
**Post date:** [July 10, 2019, 6:56pm UTC](https://discourse.julialang.org/t/destructuring-setindex/25475/9 "2019-07-10T18:56:41Z")

</div>

I filed an [issue, 32547](https://github.com/JuliaLang/julia/issues/32547) and got a clear reply that

```julia
A[1][1], A[2][2], b[3] = (1, 2, 3)

```

and

```julia
x,(y,z) = (1, (2,3)) 

```

are both intended.

I guess we can go ahead with filing a doc PR. @Tamas_Papp, would you care to take the lead?

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [July 11, 2019, 3:42am UTC](https://discourse.julialang.org/t/destructuring-setindex/25475/10 "2019-07-11T03:42:54Z")

</div>

Yes, will make a PR.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [July 11, 2019, 7:11am UTC](https://discourse.julialang.org/t/destructuring-setindex/25475/11 "2019-07-11T07:11:20Z")

</div>

[https://github.com/JuliaLang/julia/pull/32553](https://github.com/JuliaLang/julia/pull/32553)
