Why Julia can execute code when macros are expanded?

Hi, when I read the section of metaprogramming in Tom Kwong’s Book “Hands-on Design Patterns and Best Practices with Julia”, I came across such an example:

macro identity(ex)
return ex end

And then when we define such a function in REPL as:

I am a little bit curious how Julia can execute the instruction dump(ex) when the macro is expanded, since we just define the function.
Or can anyone explain the mechanism, when julia internally parses the macro like this which does not include instruction in an expression?


Macro is just a special function, it’s whole point is to execute code to do expression transformation. That’s literally what “macro expansion” means in julia and it shouldn’t be a surprise that code execution happens.

If you want to know how it’s implemented, well, as I said, it’s jus a function that the runtime knows how to call. Iif you want to know why your code runs at expansion time but you expect it to run at runtime, then that’s because you need to return the new expression to do whatever you want at runtime. You need to return an expression that does dump(ex). sth like return $(dump($(QuoteNode(ex))); $(esc(ex)))


I think

I think you meant return :(dump($(QuoteNode(ex))); $(esc(ex)))


Thanks, but I am wondering if as you said in this case, the macro returns the expressions as a whole, how the compiler can recognize what part of code should be execute at the parse time and compiling time, as the example given in the manual:

julia> macro twostep(arg)
           println("I execute at parse time. The argument is: ", arg)
           return :(println("I execute at runtime. The argument is: ", $arg))
@twostep (macro with 1 method)
julia> ex = macroexpand(Main, :(@twostep :(1, 2, 3)) );
I execute at parse time. The argument is: :((1, 2, 3))

None of the code returned runs at parse time. Your first println is not part of the code returned. It’s just the body of the function.


Thanks, I understand.