Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to evaluate Julia expression defining and calling a macro?

I am generating some code that is later being evaluated. Even though the generated code is correct and evaluating it line by line does not cause issues, it fails to be correctly evaluated as a whole.

eval(quote
  macro m() "return" end
  @m()
end)

Returns: ERROR: LoadError: UndefVarError: @m not defined

eval(quote macro m() "return" end end)
eval(@m())

Returns: "return"

like image 259
keorn Avatar asked Sep 26 '19 09:09

keorn


People also ask

How to write Macros in Julia?

Macros have a dedicated character in Julia's syntax: the @ (at-sign), followed by the unique name declared in a macro NAME ... end block.

What is metaprogramming in Julia?

Metaprogramming may be defined as the programming in which we write Julia code to process and modify Julia code. With the help of Julia metaprogramming tools, one can write Julia programming code that modifies other parts of the source code file. These tools can even control when the modified code runs.

What is a symbol in Julia?

This is the essence of a symbol: a symbol is used to represent a variable in metaprogramming. Once you have symbols as a data type, of course, it becomes tempting to use them for other things, like as hash keys. But that's an incidental, opportunistic usage of a data type that has another primary purpose.


1 Answers

Macro expansion is done before evaluation, so when macro expansion occurs in this code the definition of the macro in the first expression in the block happens too late to affect the expansion of the second expression in the block. There is one special case which does what you want: the :toplevel expression type. This is automatically used for top-level global expressions in modules but you can manually construct expressions of this type like this:

ex = Expr(:toplevel,
    :(macro m() "return" end),
    :(@m())
)

And sure enough, this does what you want:

julia> eval(ex)
"return"

Since Julia doesn't have locally scoped macros, this macro definition has to take place in global scope already so presumably this should work anywhere that the original macro would have worked—i.e. a macro definition should be valid in all the same places that a top-level compound expression is valid.

like image 198
StefanKarpinski Avatar answered Sep 28 '22 05:09

StefanKarpinski