Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I define a julia macro that defines a macro?

Tags:

macros

julia

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.

like image 633
HaberdashPI Avatar asked May 15 '17 18:05

HaberdashPI


People also ask

How do you write a macro definition?

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(;).

Can you define a macro in a function?

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.

Which command is used to define a macro variable?

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.

What is a macro in Julia?

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.


1 Answers

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
like image 91
Fengyang Wang Avatar answered Oct 21 '22 08:10

Fengyang Wang