How to define a julia macro that defines a macro?

I would think this would work:

macro meta_meta(x,y) :(macro $x(arg) :($($y) + $arg) end) end 

The expected behavior is that the call to @meta_meta(f,2) should be equivalent to macro f(arg) :(2 + $arg) end

In other words:

 julia> @meta_meta(f,2) julia> @f(3) 5 

Instead, I get:

 ERROR: syntax: invalid macro definition 

I will lose a little how to act. I see that the expression tree for this macro is different from the one I get if I manually generate @f and examine its expression tree and I tried several iterations of @meta_meta, but I canโ€™t figure out how to change my definition to force it work.

+5
source share
1 answer

Macro hygiene is a bit concise when using a quote inside a quote. Often I find that the only way is to completely abandon macrohygiene and use gensym for simulation.

However, in your example, it is just simple to include an internal quote in Expr :

 julia> macro meta_meta(x, y) :(macro $(esc(x))(arg) Expr(:call, :+, $(esc(y)), esc(arg)) end) end @meta_meta (macro with 1 method) julia> @meta_meta f 2 @f (macro with 1 method) julia> @f 3 5 

If things get more complicated, the approach I mentioned above includes disabling macro-aggregation using esc . This means that we must do hygiene ourselves, so gensym :

 julia> macro meta_meta(x, y) arg = gensym() esc(:(macro $x($arg) :($$y + $$arg) end)) end @meta_meta (macro with 1 method) julia> @meta_meta f 2 @f (macro with 1 method) julia> @f 3 5 
+6
source

All Articles