# How to return a macro from a macro?

**URL:** <https://discourse.julialang.org/t/how-to-return-a-macro-from-a-macro/139612>\
**Category:** General Usage\
**Tags:** question, macros\
**Created:** [September 22, 2026, 4:46pm UTC](https://discourse.julialang.org/t/how-to-return-a-macro-from-a-macro/139612 "2026-09-22T16:46:15Z")\
**Posts on this page:** 1\
**Showing post:** 2

<div class="post-metadata">

**Author:** ![eldee](https://avatars.discourse-cdn.com/v4/letter/e/b5a626/32.png) [@eldee](https://discourse.julialang.org/u/eldee)\
**Post date:** [September 22, 2026, 7:32pm UTC](https://discourse.julialang.org/t/how-to-return-a-macro-from-a-macro/139612/2 "2026-09-22T19:32:47Z")

</div>

Hi, and welcome to the Julia community!

* * *

I’m not sure I completely understand what you want to achieve (i.e. why this is easier than just writing

```julia
macro foo(a::Integer, b, c)
    println(a + b + c)
end

```

directly, or just creating a `function`), so perhaps a more complicated example would be useful. But for this case I guess

```julia
macro macwo(header::Expr, body::Expr)
    esc(quote
        macro $(header.args[1])($(header.args[2:end]...))
            $body
        end
    end)
end

```

works:

```julia-repl
julia> @macwo foo(a::Integer, b, c) begin
    println(a + b + c)
end
@foo (macro with 1 method)

julia> @foo(1, 2, 3)
6

```

The idea here is that we want to output essentially the same macro (expression) as I typed at the start of my post

```julia-repl
julia> using MacroTools

julia> @macroexpand @macwo foo(a::Integer, b, c) begin
           println(a + b + c)
       end
quote
    #= REPL[1]:3 =#
    macro foo(a::Integer, b, c)
        #= REPL[1]:3 =#
        #= REPL[1]:4 =#
        begin
            #= REPL[5]:2 =#
            println(a + b + c)
        end
    end
end

```

(Without the [escaping](https://docs.julialang.org/en/v1/manual/metaprogramming/#Hygiene) `esc` we would have `Main.foo`, `Main.Integer` and `Main.println`.) Now, to write our macro `macwo` it is useful to take a look at the input we are getting:

```julia-repl
julia> macro show_args(header, body)
           dump(header)
           dump(body)
       end
@show_args (macro with 1 method)

julia> @show_args foo(a::Integer, b, c) begin
           println(a + b + c)
       end
Expr
  head: Symbol call
  args: Array{Any}((4,))
    1: Symbol foo
    2: Expr
      head: Symbol ::
      args: Array{Any}((2,))
        1: Symbol a
        2: Symbol Integer
    3: Symbol b
    4: Symbol c
Expr
  head: Symbol block
  args: Array{Any}((2,))
    1: LineNumberNode
      line: Int64 2
      file: Symbol REPL[11]
    2: Expr
      head: Symbol call
      args: Array{Any}((2,))
        1: Symbol println
        2: Expr
          head: Symbol call
          args: Array{Any}((4,))
            1: Symbol +
            2: Symbol a
            3: Symbol b
            4: Symbol c

```

In this way we can see that our method name `foo` can be found as `header.args[1]`, while the argument list is present in `header.args[2:end]`, which we [splat (and interpolate)](https://docs.julialang.org/en/v1/manual/metaprogramming/#Splatting-interpolation) to get three arguments instead of a single length-3 array.

You could also add additional checks, depending on how robust you want your macro to be. For example, we expect `header.head === :call`. Currently,

```julia-auto
@macwo foo[a::Integer, b, c] begin
     println(a + b + c)
end

```

would behave identically, even though here `header.head === :ref`.

```julia-repl
julia> macro macwo(header::Expr, body::Expr)
           @assert header.head === :call
           esc(quote
               macro $(header.args[1])($(header.args[2:end]...))
                   $body
               end
           end)
       end
@macwo (macro with 1 method)

julia> @macwo foo(a::Integer, b, c) begin
           println(a + b + c)
       end
@foo (macro with 1 method)

julia> @macwo foo[a::Integer, b, c] begin
           println(a + b + c)
       end
ERROR: LoadError: AssertionError: header.head === :call
(...)

```

* * *

Edit: An alternative to inspecting the expression tree, is to use `MacroTools.jl`’s `@capture`, which can be easier to read:

```julia
macro macwo(header::Expr, body::Expr)
    @capture(header, f_(a__))
    esc(quote
        macro $f($(a...))
            $body
        end
    end)
end

```

* * *

By the way, I see that the automatic translation thinks you wrote the original message in Japanese, and that it ‘translated’ “receives” to “takes”. This might be a relevant issue for [Testing automatic translations to English](https://discourse.julialang.org/t/testing-automatic-translations-to-english/139522).

---

_[View the full topic](https://discourse.julialang.org/t/how-to-return-a-macro-from-a-macro/139612)._
