I would have thought this would work:
macro meta_meta(x,y)
:(macro $x(arg) :($($y) + $arg) end)
end
The expected behavior is that calling @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'm at a bit of a loss for how to proceed. 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've tried several iterations of @meta_meta, but I cannot figure out how to change my definition to get it working.
A macro is a piece of code in a program that is replaced by the value of the macro. Macro is defined by #define directive. Whenever a macro name is encountered by the compiler, it replaces the name with the definition of the macro. Macro definitions need not be terminated by a semi-colon(;).
Function-like macros can take arguments, just like true functions. To define a macro that uses arguments, you insert parameters between the pair of parentheses in the macro definition that make the macro function-like. The parameters must be valid C identifiers, separated by commas and optionally whitespace.
Macro Variables. All macros must start with DEFINE and end with ! ENDDEFINE . These commands identify the beginning and end of a macro definition and are used to separate the macro definition from the rest of the command sequence. Immediately after DEFINE , specify the macro name.
Answer: Macros are sort of functions which take as input unevaluated expressions. ( Expr ) and return as output. another expression, whose code is then regularly evaluated at runtime. This post isn't a. substitute for reading the section about macros in the Julia.
Macro hygiene is a little finnicky when dealing with a quote inside a quote. Often I find the only way is to refuse macro hygiene entirely, and use gensym
liberally to simulate it.
However in your reduced example, it's straightforward to just turn the inner quote into an 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 involves turning off macro hygiene with esc
. This means that we have to do the hygiene ourself, hence the 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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With