# Metaprogramming - Variable scope in macros combined with closures

**URL:** <https://discourse.julialang.org/t/metaprogramming-variable-scope-in-macros-combined-with-closures/117594>\
**Category:** New to Julia\
**Tags:** macros\
**Created:** [July 29, 2024, 2:25pm UTC](https://discourse.julialang.org/t/metaprogramming-variable-scope-in-macros-combined-with-closures/117594 "2024-07-29T14:25:14Z")\
**Posts on this page:** 5\
**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:** [July 29, 2024, 2:25pm UTC](https://discourse.julialang.org/t/metaprogramming-variable-scope-in-macros-combined-with-closures/117594/1 "2024-07-29T14:25:14Z")

</div>

Hi,

this is my first post. I have a question about macros and closures. The example is from the Book “LetOverLambda” Chapter 5.7. The author called it DLambda.  
The following source is a easy counter closure

```julia
function counter()
    count = 0
    return (msg) -> if msg == :inc 
                        count = count +1
                    elseif msg == :dec
                        count = count -1
                    end
end

```

if I do. The result is 2. Everything fine

```julia
c1 = counter()
c1(:inc)
c1(:inc)

```

Now I want abstract it away with a macro

```julia
macro counter_macro(msg, p1)
    return quote
        if $msg == :inc
            () -> println($p1)
        end
    end
end
function counter1()
    counter123 = 0
    return (@counter_macro :inc counter123)
end

```

**But then there is a error, because counter123 is NOT defined.** The problem is, that he want to use Main.counter123 as variable.  
**How can I solve this, suchthat counter1 is a closure und has the same result than counter?**

```julia
@macroexpand @counter_macro :inc counter123

```

---

<div class="post-metadata">

**Author:** ![abraemer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraemer/32/51403_2.png) [@abraemer](https://discourse.julialang.org/u/abraemer)\
**Post date:** [July 29, 2024, 2:34pm UTC](https://discourse.julialang.org/t/metaprogramming-variable-scope-in-macros-combined-with-closures/117594/2 "2024-07-29T14:34:02Z")

</div>

Hi there!  
What is your question about the code?

Also note that this example has nothing to do with metaprogramming/macros. You define a _closure_, which is essentially just a function that carries along some extra state (in this case the variable `count`). You could write an equivalent code (and in fact this is what Julia does internally):

```julia
# struct to hold the state
struct Counter
    count::Int
end

# this is the function you wrote
function counter()
    return Counter(0) # just create an instance of Counter starting at 0
end

# this makes the instance callable
function (counter::Counter)(msg)
    if msg == :inc
        counter.count += 1
    elseif msg == :dec
        counter.count -= 1
    end
end

```

---

<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:** [July 29, 2024, 2:39pm UTC](https://discourse.julialang.org/t/metaprogramming-variable-scope-in-macros-combined-with-closures/117594/3 "2024-07-29T14:39:21Z")

</div>

sorry…i needed some time to write the post. now it is ready

---

<div class="post-metadata">

**Author:** ![abraemer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraemer/32/51403_2.png) [@abraemer](https://discourse.julialang.org/u/abraemer)\
**Post date:** [July 29, 2024, 2:46pm UTC](https://discourse.julialang.org/t/metaprogramming-variable-scope-in-macros-combined-with-closures/117594/4 "2024-07-29T14:46:02Z")

</div>

Don’t worry 🙂

The issue you are facing here is because Julia has [automatic macro hygiene](https://docs.julialang.org/en/v1/manual/metaprogramming/#Hygiene). This essentially means that every symbol that a macro returns is `gensym`ed. So when you interpolate the variable name here `() -> println($p1)` then it will be a different symbol after macro expansion, which explains the error. You need to `esc`ape the symbol:

```julia
macro counter_macro(msg, p1)
    return quote
        if $msg == :inc
            () -> println($(esc(p1)))
        end
    end
end

```

With this your function `counter1()` returns a closure that prints the value of the captured variable `counter123` when called.

Edit: You would face the same problem with `msg` if tried to use a variable/expression at the call site. It only works for a constant value.

---

<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:** [July 29, 2024, 2:54pm UTC](https://discourse.julialang.org/t/metaprogramming-variable-scope-in-macros-combined-with-closures/117594/5 "2024-07-29T14:54:48Z")

</div>

Thanks a lot…it was so easy. i thought about the ESC command, but i didnt get it 🙂
