# Understanding macro lexical bindings

**URL:** https://discourse.julialang.org/t/understanding-macro-lexical-bindings/125105
**Category:** General Usage
**Tags:** macros, metaprogramming
**Created:** [January 23, 2025, 9:07am UTC](https://discourse.julialang.org/t/understanding-macro-lexical-bindings/125105 "2025-01-23T09:07:13Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![nietzsche](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nietzsche/32/214748_2.png) [@nietzsche](https://discourse.julialang.org/u/nietzsche)
#### Post date: [January 23, 2025, 9:07am UTC](https://discourse.julialang.org/t/understanding-macro-lexical-bindings/125105/1 "2025-01-23T09:07:13Z")

</div>

Hello,

the macroexpand in the code below lead to an Error.  
`UndefVarError: i not defined`  
Ther error is clear, but how can I solve it? Or how can I put the “i” from the for loop in the right environment?

```julia
macro dlamdba(body...)
    quote
        #println(length($(body)))
        (msg) ->            
            begin
                for i = 1:2
                    println((i))
                    if msg == $(body[i].args[1])
                        println(msg)
                        $(esc(body[i].args[2]))()
                    end
                end  
            end
    end
end
@macroexpand @dlamdba [:inc,() -> count = count +1] [:dec,() -> count = count -1] 

```

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [January 23, 2025, 9:38am UTC](https://discourse.julialang.org/t/understanding-macro-lexical-bindings/125105/2 "2025-01-23T09:38:05Z")

</div>

`i` only exists in the quote as a symbol, it’s not a variable until after the macro returns. Executing `body[i].args[1]` before interpolation into the quote doesn’t work because there’s no `i` variable.

I think the fundamental issue is you’re trying to write a for loop that changes subexpressions per iteration. That’s not something Julia code can do, so macros can’t transform code into that. You only have so many arguments for `@dlambda`, so you could just execute them all in sequence, like a fully unrolled loop. You can’t really write that in a quote, but you can mutate the `Expr` that the quote instantiates. Write out the unrolled loop and examine the `Expr` structure with `dump` to get an idea of how to mutate towards that.

---

<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: [January 23, 2025, 12:59pm UTC](https://discourse.julialang.org/t/understanding-macro-lexical-bindings/125105/3 "2025-01-23T12:59:55Z")

</div>

While @Benny’s answer is of course true, I think a potentially more helpful answer is that you need to do the loop over `i` inside the macro, rather than leaving it as quoted code.

i.e. something like

```julia
macro dlamdba(body...)
    f_body = Expr(:block)
    for i ∈ 1:2
        ex = quote
            println($i)
            if msg == $(esc(body[i].args[1]))
                println(msg)
                $(esc(body[i].args[2]))()
            end
        end
        push!(f_body.args, ex)
    end
    :(msg -> $f_body)
end

```
