# Namedtuple destructuring in macro fails roughly due to macro hygiene (since gensym goes eagerly)

**URL:** <https://discourse.julialang.org/t/namedtuple-destructuring-in-macro-fails-roughly-due-to-macro-hygiene-since-gensym-goes-eagerly/86172>\
**Category:** General Usage\
**Tags:** macros, syntax, destructuring\
**Created:** [August 23, 2022, 5:26am UTC](https://discourse.julialang.org/t/namedtuple-destructuring-in-macro-fails-roughly-due-to-macro-hygiene-since-gensym-goes-eagerly/86172 "2022-08-23T05:26:32Z")\
**Posts on this page:** 3\
**Page:** 1

<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:** [August 23, 2022, 5:26am UTC](https://discourse.julialang.org/t/namedtuple-destructuring-in-macro-fails-roughly-due-to-macro-hygiene-since-gensym-goes-eagerly/86172/1 "2022-08-23T05:26:32Z")

</div>

Here is the situation

```julia
f(x) = (; a=2x, b=x*x)

macro ma(x)
    quote
        f($x)
    end
end

macro mb(x)
    quote
        nt = f($x)
        (; nt.a, nt.b)
    end
end

macro mc(x)
    quote
        (; a,b) = f($x)
    end
end

```

while ma and mb behaves kindly IMO

```julia
using Test
@test (@ma 1) == (; a=2, b=1) # ok
@test (@mb 1) == (; a=2, b=1) # ok

```

```julia
@test (@mc 1) == (; a=2, b=1) # bug

```

mc errors immediately (at the lowerer ?)  
There may be some unification issues in regard to non-escaped / re-gensymd a,b  
but we should be able to destructure first IMO .  
Comment advices welcome

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [August 23, 2022, 10:45am UTC](https://discourse.julialang.org/t/namedtuple-destructuring-in-macro-fails-roughly-due-to-macro-hygiene-since-gensym-goes-eagerly/86172/2 "2022-08-23T10:45:12Z")

</div>

```julia
macro md(x)
    nt = :((; a, b))
    quote
        $(esc(nt)) = f($x)
    end
end

```

```julia
julia> @macroexpand @mc 1
quote
    #= Untitled-1:67 =#
    (; a = Main.a, b = Main.b) = Main.f(1)
end

julia> @macroexpand @md 1
quote
    #= Untitled-1:74 =#
    (; a, b) = Main.f(1)
end

```

Yes this seems kind of buggy/ill-defined to me. If the symbols a and b are not escaped, I would expect the output to be something like `(; var"#1#a", var"#2#b") = ...` because the new variables should have gensymmed names. Instead these `a = Main.a` assignments are created, which of course cannot work.

But because gensymmed names would not access the correct variables from the destructured object, this also cannot work.

Interesting case because property access and variable creation are intertwined in this syntax, and while property symbols are not subject to macro hygiene, variable creation is, so that is kind of incompatible.

---

<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:** [September 8, 2022, 9:14am UTC](https://discourse.julialang.org/t/namedtuple-destructuring-in-macro-fails-roughly-due-to-macro-hygiene-since-gensym-goes-eagerly/86172/3 "2022-09-08T09:14:35Z")

</div>

IMO the issues come from the fact the lowerer does too few passes eg. 5 passes only, first one is ~ 2.5KLOC of femtolisp. It’s a monolithic (and archaic) code nowadays.  
There should be many more passes (compare to go, rust, fsharp, no surprise, they all go this way).  
This will be possible to stage those kinds of issues correctly  
JuliaSyntax will be important at some point, (and countdown has begun a couple of years ago)
