Thanks for that clarification.
Just to really confirm, def is expanded at the same phase as other macros, but with def the expanded AST is stored and used later. Which would mean that the below is exemplifying the order of expansion for all intents and purposes, due to actual exposure of the def
AST’s effects via emittance of the module byte code?
Order of expansion
As you’d expect, the module-level code (the code that isn’t a part of any function) is evaluated in the expansion phase. Somewhat surprisingly, this will happen after all macros (save for
def
) have been expanded. It’s easy to prove this:
defmodule MyMacro do defmacro my_macro do IO.puts "my_macro called" nil end end
defmodule Test do import MyMacro IO.puts "module-level expression" my_macro end # Output: my_macro called module-level expression
See from the output how
mymacro
is called beforeIO.puts
even though the correspondingIO.puts
call precedes the macro call. This proves that compiler first resolves all “standard” macros. Then the module generation starts, and it is in this phase where module-level code, together with calls todef
is being evaluated.
excerpt from Understanding Macros Part 6