# Destructuring syntax in julia 1.7

**URL:** <https://discourse.julialang.org/t/destructuring-syntax-in-julia-1-7/68236>\
**Category:** Internals & Design\
**Tags:** destructuring\
**Created:** [September 15, 2021, 11:01pm UTC](https://discourse.julialang.org/t/destructuring-syntax-in-julia-1-7/68236 "2021-09-15T23:01:36Z")\
**Posts on this page:** 20\
**Page:** 3

<div class="post-metadata">

**Author:** ![ettersi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ettersi/32/6829_2.png) [@ettersi](https://discourse.julialang.org/u/ettersi)\
**Post date:** [October 15, 2021, 12:35am UTC](https://discourse.julialang.org/t/destructuring-syntax-in-julia-1-7/68236/42 "2021-10-15T00:35:56Z")

</div>

I’m aware of that logic and I agree that it is quite clever. My worry is mainly that it is a bit too clever.

Playing along with these ideas, one could argue that `(1; a=2)` should be a mixed positional and named tuple. Instead, it’s a shorthand `begin ... end` block equivalent to simply `a = 2`. Similarly, one might expect the following to work:

```julia
julia> (first_entry; diag) = Diagonal([1,2])
ERROR: syntax: invalid assignment location "begin
    first_entry
    # REPL[10], line 1
    diag
end" around REPL[10]:1

```

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [October 15, 2021, 2:39am UTC](https://discourse.julialang.org/t/destructuring-syntax-in-julia-1-7/68236/43 "2021-10-15T02:39:21Z")

</div>

those sound like nice features to me. If you write the PR, I’ll give it a thumbs up 😄

---

<div class="post-metadata">

**Author:** ![ericphanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ericphanson/32/215186_2.png) [@ericphanson](https://discourse.julialang.org/u/ericphanson)\
**Post date:** [October 15, 2021, 12:48pm UTC](https://discourse.julialang.org/t/destructuring-syntax-in-julia-1-7/68236/44 "2021-10-15T12:48:43Z")

</div>

Ref [https://github.com/ararslan/FrankenTuples.jl](https://github.com/ararslan/FrankenTuples.jl)

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [October 15, 2021, 2:09pm UTC](https://discourse.julialang.org/t/destructuring-syntax-in-julia-1-7/68236/45 "2021-10-15T14:09:20Z")

</div>

The `(expr1; expr2)` syntax for a block long predates named tuples. You’re right that if we’d had foreseen that it would eventually make sense as a frakentuple syntax, then we might have reserved the syntax for that. Of course, I’m not sure if frankentuples will even be added to the language, let alone need a syntax, so for now the fact that this syntax means something else seems fine. Syntax collisions happen and when they do, you just have to pick one of the possible meanings (or error because it’s ambiguous, but that’s kind of annoying).

---

<div class="post-metadata">

**Author:** ![o314](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/o314/32/252_2.png) [@o314](https://discourse.julialang.org/u/o314)\
**Post date:** [February 11, 2022, 6:42pm UTC](https://discourse.julialang.org/t/destructuring-syntax-in-julia-1-7/68236/46 "2022-02-11T18:42:54Z")

</div>

A nice but missing close feature AFAIK, will be to convert a tuple to a namedtuple given some names.

Suppose one needs to compute something upon the datum `v = (1, 2, 3)`  
But let suppose again that we prefer to handle it thru syntax `v.x * v.x - v.y * v.y` rather than `v[1] * v[1] - v[2] * v[2]`

Today, one can do the following

```julia
v = NamedTuple((:x,:y,:z) .=> v) # a bit awkward

```

or

```julia
v = (; ((:x,:y,:z) .=> v)...) # a bit very awkward

```

but not

```julia
v = (; (:x,:y,:z) .=> v) # for example

```

to finally get

```julia
using Test
@test v.x * v.x - v.y * v.y == -3

```

Some syntax may be alleviated there…

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [February 11, 2022, 6:47pm UTC](https://discourse.julialang.org/t/destructuring-syntax-in-julia-1-7/68236/47 "2022-02-11T18:47:09Z")

</div>

> [@o314](#):
>
> `v.x * v.x - v.y * v.y` rather than `v[1] * v[1] - v[2] * v[2]`

just:

```julia
vx, vy, vz = v

```

??? and `vx` is easier to type than `v.x`… and we don’t create type instability Tuple =\> NamedTuple

---

<div class="post-metadata">

**Author:** ![o314](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/o314/32/252_2.png) [@o314](https://discourse.julialang.org/u/o314)\
**Post date:** [February 11, 2022, 7:03pm UTC](https://discourse.julialang.org/t/destructuring-syntax-in-julia-1-7/68236/48 "2022-02-11T19:03:58Z")

</div>

This is an example. You will not be able to flatten everything everywhere with only oneliners.  
Think to a function call with some args, tuples or not; a body with many if branches.  
Oneliners will not scale

Type can be infer very simply.

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [February 11, 2022, 7:08pm UTC](https://discourse.julialang.org/t/destructuring-syntax-in-julia-1-7/68236/49 "2022-02-11T19:08:09Z")

</div>

> [@o314](#):
>
> Type can be infer very simply.

r i g h t

 ![image](https://global.discourse-cdn.com/julialang/original/3X/6/c/6ce23656c9372de6b42036185c78d070be87edd7.png)  
(and it doesn’t go away even if you use `g = NamedTuple...`:

```julia
│ %5 = Base.getproperty(g, :x)::Any
│ %6 = Base.getproperty(g, :y)::Any
│ %7 = (%5 + %6)::Any

```

* * *

> [@o314](#):
>
> You will not be able to flatten everything everywhere with only oneliners.

you’re still typing `:x ,:y`, I don’t see how that’s easier than `vx, vx = `; what would be additionally useful is keyword destruction with renaming, but that one will have counterintuitive syntax at first glance so probably won’t be in Base in a while

---

<div class="post-metadata">

**Author:** ![o314](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/o314/32/252_2.png) [@o314](https://discourse.julialang.org/u/o314)\
**Post date:** [February 11, 2022, 7:42pm UTC](https://discourse.julialang.org/t/destructuring-syntax-in-julia-1-7/68236/51 "2022-02-11T19:42:59Z")

</div>

This is a syntaxic form proposal. Do not erase too much things !

```julia
# lowering wo excessive erasure
_2nt(v::Tuple{Int,Int,Int}) =
    NamedTuple( (:x,:y,:z) .=> v) :: @NamedTuple{x::Int,y::Int,z::Int}

```

```julia
@code_warntype _2nt((1,2,3))

Body::NamedTuple{(:x, :y, :z), Tuple{Int64, Int64, Int64}} # good
1 ─ %1 = (:x, :y, :z)::Core.Const((:x, :y, :z))
│ %2 = Base.broadcasted(Main.:(=>), %1, v)::Core.PartialStruct(Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple}, Nothing, Type{Pair}, Tuple{Tuple{Symbol, Symbol, Symbol}, Tuple{Int64, Int64, Int64}}}, Any[Core.Const(Pair), Core.PartialStruct(Tuple{Tuple{Symbol, Symbol, Symbol}, Tuple{Int64, Int64, Int64}}, Any[Core.Const((:x, :y, :z)), Tuple{Int64, Int64, Int64}]), Core.Const(nothing)])
│ %3 = Base.materialize(%2)::Core.PartialStruct(Tuple{Pair{Symbol, Int64}, Pair{Symbol, Int64}, Pair{Symbol, Int64}}, Any[Core.PartialStruct(Pair{Symbol, Int64}, Any[Core.Const(:x), Int64]), Core.PartialStruct(Pair{Symbol, Int64}, Any[Core.Const(:y), Int64]), Core.PartialStruct(Pair{Symbol, Int64}, Any[Core.Const(:z), Int64])])
│ %4 = Main.NamedTuple(%3)::NamedTuple
│ %5 = (:x, :y, :z)::Core.Const((:x, :y, :z))
│ %6 = Core.apply_type(Base.Tuple, Main.Int, Main.Int, Main.Int)::Core.Const(Tuple{Int64, Int64, Int64})
│ %7 = Core.apply_type(Base.NamedTuple, %5, %6)::Core.Const(NamedTuple{(:x, :y, :z), Tuple{Int64, Int64, Int64}})
│ %8 = Core.typeassert(%4, %7)::NamedTuple{(:x, :y, :z), Tuple{Int64, Int64, Int64}}
└── return %8

```

some calc

```julia
# inference is out of scope from desugaring from there
nt = _2nt((1,2,3))
nt.x + nt.y

```

–  
No comment about other point, my first remark was clear enough.

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [February 11, 2022, 10:26pm UTC](https://discourse.julialang.org/t/destructuring-syntax-in-julia-1-7/68236/52 "2022-02-11T22:26:46Z")

</div>

> [@o314](#):
>
> missing close feature AFAIK, will be to convert a tuple to a namedtuple given some names

Isn’t it just NamedTuple{(:x,:y,:z)}(v) ?

---

<div class="post-metadata">

**Author:** ![JeffreySarnoff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeffreysarnoff/32/1980_2.png) [@JeffreySarnoff](https://discourse.julialang.org/u/JeffreySarnoff)\
**Post date:** [April 25, 2022, 4:51pm UTC](https://discourse.julialang.org/t/destructuring-syntax-in-julia-1-7/68236/53 "2022-04-25T16:51:02Z")

</div>

@aplavin close …

```julia
> ant = (a=2, n=6, t=11)
(a = 2, n = 6, t = 11)

> tan = NamedTuple{(:t, :a, :n)}( values(ant) )
(t = 2, a = 6, n = 11)

```

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [April 25, 2022, 8:17pm UTC](https://discourse.julialang.org/t/destructuring-syntax-in-julia-1-7/68236/54 "2022-04-25T20:17:28Z")

</div>

What exactly do you want to achieve? My comment was about converting a tuple to a namedtuple by adding names.  
Looks like, you need to reorder namedtuple fields for some reason? Then ant[(:t, :a, :n)] is the easiest way.

---

<div class="post-metadata">

**Author:** ![JeffreySarnoff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeffreysarnoff/32/1980_2.png) [@JeffreySarnoff](https://discourse.julialang.org/u/JeffreySarnoff)\
**Post date:** [April 25, 2022, 8:26pm UTC](https://discourse.julialang.org/t/destructuring-syntax-in-julia-1-7/68236/55 "2022-04-25T20:26:19Z")

</div>

I misread your intent. Thank you for clarifying

---

<div class="post-metadata">

**Author:** ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)\
**Post date:** [October 18, 2022, 2:01am UTC](https://discourse.julialang.org/t/destructuring-syntax-in-julia-1-7/68236/56 "2022-10-18T02:01:50Z")

</div>

Wanted to destructure a dictionary, found this convenient:

```julia
mydict = Dict(:x=>1, :y=>2, :z=>3)
(; x, y) = NamedTuple(mydict)

```

Unfortunately it works only for dictionaries whose keys are symbols, `Dict{Symbol, T}`. It doesn’t work for a dictionary whose keys are strings `Dict{String, T}` (as is frequently the case for config files, etc.).

This can be addressed by overloading `NamedTuple` to convert string keys to symbols:

```julia
NamedTuple(d::Dict{String,T} where T) = NamedTuple{Tuple(Symbol(k) for k ∈ keys(d))}(v for v ∈ values(d))

```

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [October 18, 2022, 3:31pm UTC](https://discourse.julialang.org/t/destructuring-syntax-in-julia-1-7/68236/57 "2022-10-18T15:31:20Z")

</div>

> [@uniment](#):
>
> This can be addressed by overloading `NamedTuple` to convert string keys to symbols:

Note that this is type piracy, and is generally frowned upon. You don’t own any of the functions or types here, so should generally be avoided.

Also, the conversion to `NamedTuple` is type unstable, so using that will probably be slower than necessary, even than regular `Dict` indexing.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [October 18, 2022, 4:19pm UTC](https://discourse.julialang.org/t/destructuring-syntax-in-julia-1-7/68236/58 "2022-10-18T16:19:43Z")

</div>

> [@uniment](#):
>
> Wanted to destructure a dictionary

Note that you can use the destructuring syntax with any datatype that supports `getproperty`. So, for example, if you use [PropDicts.jl](https://github.com/oschulz/PropDicts.jl), you can do:

```julia
julia> using PropDicts

julia> mydict = PropDict(:x=>1, :y=>2, :z=>3)
PropDict with 3 entries:
  :y => 2
  :z => 3
  :x => 1

julia> (; x, y) = mydict;

julia> x, y
(1, 2)

```

(Unlike conversion to `NamedTuple`, this is type-stable, at least with a typed `PropDict`, and should be equivalent to `x = mydict[:x], y = mydict[:y]`.)

---

<div class="post-metadata">

**Author:** ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)\
**Post date:** [October 19, 2022, 4:49am UTC](https://discourse.julialang.org/t/destructuring-syntax-in-julia-1-7/68236/59 "2022-10-19T04:49:02Z")

</div>

> [@Sukera](#):
>
> Also, the conversion to `NamedTuple` is type unstable, so using that will probably be slower than necessary, even than regular `Dict` indexing.

This is a good point.

If I understand correctly, the concerns here are:

- returning a tuple of _variable length_
- returning a tuple whose type parameterization is an _unknown sequence_ of `Symbol` names

Is this correct? I hope to understand it properly.

> [@stevengj](#):
>
> Note that you can use the destructuring syntax with any datatype that supports `getproperty`.

Thanks for the input! I’ve been playing with making my own toy `PropDict`-like datatype and came to this realization. Naturally I like mine better, but that’s a different story.

Along this vein, something I found weird: tab-autocomplete of property names seems to depend on `Base.propertynames(d::D)` existing. However, for all of `PropDicts`, `PropertyDicts`, and for my own datatype too, tab-autocomplete doesn’t work beyond the first nesting level.

For example:

```julia
using PropDicts
a = PropDict()
a[:a] = PropDict()
a.a[:a] = PropDict()
a.a.a[:a] = PropDict()

julia> a.<tab> # autocompletes to a.a

julia> a.a.<tab> # no autocomplete

```

By contrast, structs do autocomplete to deeper nesting depths:

```julia
struct MyStruct a end
a = MyStruct(MyStruct(MyStruct(nothing)))

julia> a.<tab> # autocompletes to a.a

julia> a.a.<tab> # autocompletes to a.a.a

julia> a.a.a.<tab> # autocompletes to a.a.a.a

```

Do you have any clue what’s going on here? Am I missing something?

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [October 19, 2022, 6:40am UTC](https://discourse.julialang.org/t/destructuring-syntax-in-julia-1-7/68236/60 "2022-10-19T06:40:24Z")

</div>

> [@uniment](#):
>
> Is this correct? I hope to understand it properly.

Not just that, but accessing the elements of that `NamedTuple` is also going to require a lookup due to only being able to infer `Any`. That’s ultimately what’s going to make this slower than just having the dict accesses there, since such a type instability is pretty infectious.

---

<div class="post-metadata">

**Author:** ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)\
**Post date:** [October 19, 2022, 6:47am UTC](https://discourse.julialang.org/t/destructuring-syntax-in-julia-1-7/68236/61 "2022-10-19T06:47:13Z")

</div>

> [@uniment](#):
>
> It doesn’t work for a dictionary whose keys are strings `Dict{String, T}` (as is frequently the case for config files, etc.).

You may use `UnPack.jl` for this.

```julia
julia> using UnPack

julia> D = Dict("a"=>1, "b"=>2)
Dict{String, Int64} with 2 entries:
  "b" => 2
  "a" => 1

julia> @unpack a, b = D;

julia> a
1

julia> b
2

```

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [October 19, 2022, 12:15pm UTC](https://discourse.julialang.org/t/destructuring-syntax-in-julia-1-7/68236/62 "2022-10-19T12:15:36Z")

</div>

> [@Sukera](#):
>
> Not just that, but accessing the elements of that `NamedTuple` is also going to require a lookup due to only being able to infer `Any`.

Would it really infer `Any`? Even for something like `NamedTuple{NS, NTuple{N, Int}} where {NS, N}`?

[Previous page](https://discourse.julialang.org/t/destructuring-syntax-in-julia-1-7/68236.md?page=2)

[Next page](https://discourse.julialang.org/t/destructuring-syntax-in-julia-1-7/68236.md?page=4)
