# Importing a macro within another macro

**URL:** <https://discourse.julialang.org/t/importing-a-macro-within-another-macro/25550>\
**Category:** General Usage\
**Created:** [June 22, 2019, 7:52pm UTC](https://discourse.julialang.org/t/importing-a-macro-within-another-macro/25550 "2019-06-22T19:52:32Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![phrmoy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/phrmoy/32/8912_2.png) [@phrmoy](https://discourse.julialang.org/u/phrmoy)\
**Post date:** [June 22, 2019, 7:52pm UTC](https://discourse.julialang.org/t/importing-a-macro-within-another-macro/25550/1 "2019-06-22T19:52:32Z")

</div>

Why doesn’t this work?

```julia
macro verify()
    return esc(quote
        using julia_utils: @add_default_constructor
        mutable struct A
            a::Int
            A() = new()
        end
        @add_default_constructor A
    end)
end
@verify

```

gives

```julia
ERROR: LoadError: LoadError: UndefVarError: @add_default_constructor not defined

```

However,

```julia
macro verify()
    return esc(quote
        using julia_utils: @add_default_constructor
    end)
end
@verify
mutable struct A       
    a::Int
    A() = new()
end
@add_default_constructor A

```

works just fine.

---

<div class="post-metadata">

**Author:** ![ffevotte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ffevotte/32/6587_2.png) [@ffevotte](https://discourse.julialang.org/u/ffevotte)\
**Post date:** [June 22, 2019, 8:15pm UTC](https://discourse.julialang.org/t/importing-a-macro-within-another-macro/25550/2 "2019-06-22T20:15:33Z")

</div>

This is because the `@add_default_constructor` macro expansion happens during the `@verify` macro expansion, and not during the evaluation of the result of `@verify`.

To make things maybe a bit clearer, let’s separate the two macro expansion phases:

```julia
# Fake module, so that things are self-sufficient
module julia_utils
macro add_default_constructor(x)
    "OK"
end
end

macro verify()
    quote
        using .julia_utils: @add_default_constructor
        mutable struct A
            a::Int
            A() = new()
        end
        @add_default_constructor A
    end |> esc
end

```

This is the first (non-recursive) macro expansion:

```julia
julia> @macroexpand1 @verify
quote
    #= REPL[2]:3 =#
    using .julia_utils: @add_default_constructor
    #= REPL[2]:4 =#
    mutable struct A
        #= REPL[2]:5 =#
        a::Int
        #= REPL[2]:6 =#
        A() = begin
                #= REPL[2]:6 =#
                new()
            end
    end
    #= REPL[2]:8 =#
    #= REPL[2]:8 =# @add_default_constructor A
end

```

As you can see, everything goes well at this stage. But then the output of `@verify` contains a macro call. Before evaluating this output syntax, Julia has to expand this second macro call. Let me re-iterate to make this very clear: the `@add_default_constructor` macro call gets expanded _before_ the output syntax of `@verify` begins evaluating. At this stage, `julia_utils.@add_default_constructor` is still unknown, since it will be added to the environment later, when the first line of the output syntax of `@verify` will be evaluated.

Does this make sense?

  

Any solution where the `using julia_utils` and the `@add_default_constructor` macro call happen in two clearly separate contexts will work. Including (but not limited to) the one you found.

An other solution would be to load the `@add_default_constructor` macro during the expansion of `@verify`:

```julia
macro verify()
    @eval using .julia_utils: @add_default_constructor
    quote
        mutable struct A
            a::Int
            A() = new()
        end
        @add_default_constructor A
    end |> esc
end

```

```julia
julia> @macroexpand @verify
quote
    #= REPL[2]:4 =#
    mutable struct A
        #= REPL[2]:5 =#
        a::Int
        #= REPL[2]:6 =#
        A() = begin
                #= REPL[2]:6 =#
                new()
            end
    end
    #= REPL[2]:8 =#
    "OK"
end

```

I guess such a solution should not be recommended since it will only work in the top-level context. But seeing the rest of the macro expansion, it should be relatively safe in this case: defining a new type will also only work at top level.

---

<div class="post-metadata">

**Author:** ![phrmoy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/phrmoy/32/8912_2.png) [@phrmoy](https://discourse.julialang.org/u/phrmoy)\
**Post date:** [June 22, 2019, 8:29pm UTC](https://discourse.julialang.org/t/importing-a-macro-within-another-macro/25550/3 "2019-06-22T20:29:06Z")

</div>

I have read this over a few times, and I am sure you have done a great job explaining this, but all I was able to take away was: `@add_default_constructor` gets expanded before `@verify` is evaluated, and for that reason `@add_default_constructor` is not yet available (known) during evaluation. If what I said is correct, I still don’t understand what I am saying, or rather, why.

---

<div class="post-metadata">

**Author:** ![phrmoy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/phrmoy/32/8912_2.png) [@phrmoy](https://discourse.julialang.org/u/phrmoy)\
**Post date:** [June 22, 2019, 8:31pm UTC](https://discourse.julialang.org/t/importing-a-macro-within-another-macro/25550/4 "2019-06-22T20:31:10Z")

</div>

> [@ffevotte](#):
>
> An other solution would be to load the `@add_default_constructor` macro during the expansion of `@verify` :
> 
> ```julia
> macro verify()
> @eval using .julia_utils: @add_default_constructor
> quote
> mutable struct A
> a::Int
> A() = new()
> end
> @add_default_constructor A
> end |> esc
> end
> 
> ```
> 
> ```julia
> julia> @macroexpand @verify
> quote
> #= REPL[2]:4 =#
> mutable struct A
> #= REPL[2]:5 =#
> a::Int
> #= REPL[2]:6 =#
> A() = begin
> #= REPL[2]:6 =#
> new()
> end
> end
> #= REPL[2]:8 =#
> "OK"
> end
> 
> ```
> 
> I guess such a solution should not be recommended since it will only work in the top-level context. But seeing the rest of the macro expansion, it should be relatively safe in this case: defining a new type will also only work at top level.

Had not seen that before responding.

---

<div class="post-metadata">

**Author:** ![phrmoy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/phrmoy/32/8912_2.png) [@phrmoy](https://discourse.julialang.org/u/phrmoy)\
**Post date:** [June 22, 2019, 9:23pm UTC](https://discourse.julialang.org/t/importing-a-macro-within-another-macro/25550/5 "2019-06-22T21:23:45Z")

</div>

Ok, this is getting clearer. Thank you!

---

<div class="post-metadata">

**Author:** ![chengchingwen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chengchingwen/32/8390_2.png) [@chengchingwen](https://discourse.julialang.org/u/chengchingwen)\
**Post date:** [June 23, 2019, 4:42am UTC](https://discourse.julialang.org/t/importing-a-macro-within-another-macro/25550/6 "2019-06-23T04:42:19Z")

</div>

Since @macro\_expand return a Expr, you can actually pass the quoted expression to macro expand and return the result in the macro definition

---

<div class="post-metadata">

**Author:** ![phrmoy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/phrmoy/32/8912_2.png) [@phrmoy](https://discourse.julialang.org/u/phrmoy)\
**Post date:** [June 23, 2019, 7:17pm UTC](https://discourse.julialang.org/t/importing-a-macro-within-another-macro/25550/7 "2019-06-23T19:17:20Z")

</div>

The `@eval` works nicely.

```julia
macro Ma(a)
    return esc(quote
        if $a <= 10
            println($a)
            @eval @Ma $a+1
        end
    end)
end
@Ma 1
1
2
3
4
5
6
7
8
9
10

```

Thanks @ffevotte.
