In the REPL, any macro is expanded as soon as we invoke it. Interestingly, when a function containing the macro is defined, the macro is expanded as part of the function definition process.
We can see this in action by developing a simple @identity macro that returns whatever expression is passed into it. Right before the expression is returned, we just dump the object to the screen. The code for the @identity macro is as follows:
macro identity(ex)
dump(ex)
return ex
end
Since this macro returns the same expression that was passed, it should end up executing the original source code that follows the macro.
Now, let's define a function that uses the @identity macro:
Clearly, the compiler has figured out that the macro is being used in the definition of the foo function and, in order to compile the foo function, it must understand what the @identity macro does. So it expanded the macro and baked that into the function definition. During the macro expansion process, the expression was displayed.
If we use the @code_lowered macro against the foo function, we can see that the expanded code is now in the body of the foo function:
The @macroexpand utility is an indispensable tool for developing macros, and in particular, is most useful for debugging purposes.
Next, we will try to be a little more creative by manipulating expressions in macros.