# Macro scoping issue

**URL:** <https://discourse.julialang.org/t/macro-scoping-issue/44919>\
**Category:** General Usage\
**Created:** [August 14, 2020, 7:38am UTC](https://discourse.julialang.org/t/macro-scoping-issue/44919 "2020-08-14T07:38:03Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![jagot](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jagot/32/12217_2.png) [@jagot](https://discourse.julialang.org/u/jagot)\
**Post date:** [August 14, 2020, 7:38am UTC](https://discourse.julialang.org/t/macro-scoping-issue/44919/1 "2020-08-14T07:38:03Z")

</div>

I have a macro that provides a small DSL and then introduces a variable in the calling scope. I noticed under some circumstances it fails, here is a MWE:

```julia
macro my_macro(var, val)
    :($(esc(var)) = $(val))
end

```

```julia
function test1()
    for i = 1:3
        @eval @my_macro(my_var, $i)
        @show my_var
    end
    @show my_var
end
test1()

```

```julia
my_var = 1
my_var = 2
my_var = 3
my_var = 3

```

I guess the `for` loop decides `my_var` does not clash with anything in the parent scope, however I did not expect `my_var` to be visible outside the loop.

When I introduce a second call to the macro, after the `for` loop, suddenly the variable is not even visible inside the loop:

```julia
function test2()
    for i = 1:3
        @eval @my_macro(my_var, $i)
        @show my_var
    end

    @my_macro(my_var, 5)
    @show my_var
end
test2()

```

```julia
ERROR: LoadError: UndefVarError: my_var not defined
Stacktrace:
 [1] macro expansion at ./show.jl:641 [inlined]

```

---

<div class="post-metadata">

**Author:** ![heliosdrm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/heliosdrm/32/3851_2.png) [@heliosdrm](https://discourse.julialang.org/u/heliosdrm)\
**Post date:** [August 14, 2020, 8:16am UTC](https://discourse.julialang.org/t/macro-scoping-issue/44919/2 "2020-08-14T08:16:36Z")

</div>

The problem is that `@eval` evaluates the following expression in the global scope, even though it is executed inside a function. Actually, after running `test1()` you’ll also have the variable `my_var` in `Main`.

I’m not sure about what’s happening in the second example, but the error does not happen if the name of the variable outside the loop is different.

---

<div class="post-metadata">

**Author:** ![jagot](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jagot/32/12217_2.png) [@jagot](https://discourse.julialang.org/u/jagot)\
**Post date:** [August 14, 2020, 8:25am UTC](https://discourse.julialang.org/t/macro-scoping-issue/44919/3 "2020-08-14T08:25:24Z")

</div>

I see, that makes sense. Also escaping `val` in the macro allows me to have `i` in the call to the macro without `@eval`:

```julia
macro my_macro(var, val)
    :($(esc(var)) = $(esc(val)))
end

function test1()
    for i = 1:3
        @my_macro(my_var, i)
        @show my_var
    end
    @show my_var
end

```

which gives

```julia
my_var = 1
my_var = 2
my_var = 3
ERROR: LoadError: UndefVarError: my_var not defined
Stacktrace:
 [1] macro expansion at ./show.jl:641 [inlined]

```

as I would expect.

I think the reason I went with `@eval` is because I have more complicated expressions in the block I pass to the macro, but I’ll keep digging. Thanks!
