# Help: Unexpected error when using a macro in a for loop

**URL:** https://discourse.julialang.org/t/help-unexpected-error-when-using-a-macro-in-a-for-loop/65555
**Category:** General Usage
**Created:** [July 30, 2021, 3:15pm UTC](https://discourse.julialang.org/t/help-unexpected-error-when-using-a-macro-in-a-for-loop/65555 "2021-07-30T15:15:03Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![josePereiro](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/josepereiro/32/17322_2.png) [@josePereiro](https://discourse.julialang.org/u/josePereiro)
#### Post date: [July 30, 2021, 3:15pm UTC](https://discourse.julialang.org/t/help-unexpected-error-when-using-a-macro-in-a-for-loop/65555/1 "2021-07-30T15:15:03Z")

</div>

Hi, short history:  
I define a macro in a module, it works fine, but when I call this macro inside a `for` it fails.  
Here a full MWE.

```julia

## ----------------------------------------------------------------
# I wants a function '_gen_macro' that generate/eval a macro in a module 'mod'
function _macro_ex(mod, exs...)
    quote
        $(mod).foo($exs) # 'foo' is expected to be in the module
    end
end

function _gen_macro(mod)
    @eval mod begin
        macro _macro(ex, exs...)
            $(_macro_ex)($mod, ex, exs...)
        end
    end
end

## ----------------------------------------------------------------
# MWE 
module A
    import Main: _gen_macro
    foo(exs...) = @info("In Mod A", length(exs...))
    _gen_macro(A)
end

## ----------------------------------------------------------------
# Tests (eval each section in sequence, not at the same time)

## this works
let
    A.@_macro 1 2 3 4
end
# Output
# ┌ Info: In Mod A
# └ length(exs...) = 4

## But this fails before run time (I think at macro-expansion?)
for Mod in [A]
    @info("This won't be printed")
    Mod.@_macro 1 2 3 4
end
# Output
# ERROR: LoadError: LoadError: UndefVarError: Mod not defined

## But 'Mod' is defined and has '@_macro' in it...
for Mod in [A]
    has_macro = isdefined(Mod, Symbol("@_macro"))
    Mod_names = join(string.(names(Mod; all = true)), ", ")
    @info("This will be printed", Mod, has_macro, Mod_names)
end
# Output
# ┌ Info: This will be printed
# │ Mod = Main.A
# │ has_macro = true
# └ Mod_names = "#@_macro, #eval, #foo, #include, @_macro, A, eval, foo, include"

```

Why does the `Mod not defined` error occur?

Thanks

[EDIT] Better title, shorter MWE

---

<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: [July 31, 2021, 8:10am UTC](https://discourse.julialang.org/t/help-unexpected-error-when-using-a-macro-in-a-for-loop/65555/2 "2021-07-31T08:10:54Z")

</div>

`eval` happens at global scope

---

<div class="post-metadata">

### Author: ![josePereiro](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/josepereiro/32/17322_2.png) [@josePereiro](https://discourse.julialang.org/u/josePereiro)
#### Post date: [July 31, 2021, 8:15pm UTC](https://discourse.julialang.org/t/help-unexpected-error-when-using-a-macro-in-a-for-loop/65555/3 "2021-07-31T20:15:25Z")

</div>

Hi, thanks. Can you elaborate further?  
This is how I think stuff happens. I call `eval` only inside the function `_gen_macro`, I call this function when I define the module `A`, so it define in the global scope of `A` the macro `@_macro`. Later I even use `A.@_macro` successfully. What I don’t understand is why the `for` loop fails. The error occurs even before the printing line is executed so I suspect any code inside `A` runs either. Also, the error said `Mod` is not define, it is like the code inside the loop is being run in a scope other than the loop.

---

<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: [July 31, 2021, 8:28pm UTC](https://discourse.julialang.org/t/help-unexpected-error-when-using-a-macro-in-a-for-loop/65555/4 "2021-07-31T20:28:04Z")

</div>

> [@josePereiro](#):
>
> `Mod.@_macro 1 2 3 4`

macro expansion happens before runtime, maybe writing it this way makes it more clear:

```julia
julia> @Base. __LINE__
1

julia> for b in [Base]
           @b. __LINE__
       end
ERROR: LoadError: UndefVarError: b not defined
in expression starting at REPL[19]:

```

---

<div class="post-metadata">

### Author: ![josePereiro](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/josepereiro/32/17322_2.png) [@josePereiro](https://discourse.julialang.org/u/josePereiro)
#### Post date: [July 31, 2021, 8:53pm UTC](https://discourse.julialang.org/t/help-unexpected-error-when-using-a-macro-in-a-for-loop/65555/5 "2021-07-31T20:53:31Z")

</div>

WOW, thanks, I didn’t know that `@Mod.macroname` is equivalent to `Mod.@macroname`.  
But, there is any workaround?  
My goal would be:  
To call a macro call `_macro` contained in several modules listed on `Mods` with the same expression as argument.

---

<div class="post-metadata">

### Author: ![josePereiro](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/josepereiro/32/17322_2.png) [@josePereiro](https://discourse.julialang.org/u/josePereiro)
#### Post date: [July 31, 2021, 8:56pm UTC](https://discourse.julialang.org/t/help-unexpected-error-when-using-a-macro-in-a-for-loop/65555/6 "2021-07-31T20:56:55Z")

</div>

I must add that I want to do that on a local scope.

```julia
Mods = [:A]
for Mod in Mods
    @info("This won't be printed")
    @eval $(Mod).@_macro 1 2 3 4
end

```

This works but is run at global scope.

---

<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: [July 31, 2021, 9:09pm UTC](https://discourse.julialang.org/t/help-unexpected-error-when-using-a-macro-in-a-for-loop/65555/7 "2021-07-31T21:09:33Z")

</div>

[https://docs.julialang.org/en/v1/base/base/#Base.@eval](https://docs.julialang.org/en/v1/base/base/#Base.@eval)

takes an optional `module` which you want to evaluate into, try that? not sure if it will work for your case

---

<div class="post-metadata">

### Author: ![josePereiro](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/josepereiro/32/17322_2.png) [@josePereiro](https://discourse.julialang.org/u/josePereiro)
#### Post date: [July 31, 2021, 9:24pm UTC](https://discourse.julialang.org/t/help-unexpected-error-when-using-a-macro-in-a-for-loop/65555/8 "2021-07-31T21:24:50Z")

</div>

Yes but that will eval the expression at the global scope of the module.  
The real macro that I’m using do assign new variables, so I want such variables to remain in the scope where I called the macro. At the same time the same macro is defined in several modules, and behave different depending on the module.  
For example I want this code:

```julia
let
   @A._macro a
   @B._macro b
end

```

to expand to:

```julia
let
   a = "From module A"
   b = "From module B"
end

```

Implicitly im using the module as the first argument of the macro. I’m maybe using an antipattern.  
This is maybe more julian.

```julia
let
   # And `esc` A
   @_macro: A a
end

```

---

<div class="post-metadata">

### Author: ![josePereiro](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/josepereiro/32/17322_2.png) [@josePereiro](https://discourse.julialang.org/u/josePereiro)
#### Post date: [July 31, 2021, 9:34pm UTC](https://discourse.julialang.org/t/help-unexpected-error-when-using-a-macro-in-a-for-loop/65555/9 "2021-07-31T21:34:07Z")

</div>

Now it works! Thanks

```julia

## ----------------------------------------------------------------
# Now the `_macro` will be defined globally and accept the module as argument
function _macro_ex(mod, exs...)
    quote
        $(esc(mod)).foo($(exs)) # 'foo' is expected to be in the module
    end
end

# Im expecting all arg to be ok
macro _macro(mod, ex, exs...)
    _macro_ex(mod, ex, exs...)
end

## ----------------------------------------------------------------
# MWE 
module A
    import Main: _gen_macro
    foo(exs...) = @info("In Mod A", length(exs...))
end

## ----------------------------------------------------------------
# Tests (eval each section in sequence, not at the same time)

## this works
let
    @_macro A 1 2 3 4
end
# Output
# ┌ Info: In Mod A
# └ length(exs...) = 4

## This is now working
for Mod in [A]
    @info("This is now printed")
    @_macro Mod 1 2 3 4
end
# Output
# [ Info: This is now printed
# ┌ Info: In Mod A
# └ length(exs...) = 4

```
