Macros are, at the core, far simpler than folks realize. Macros themselves are not complex, but sometimes the semantics of quote
and unquote
can be, and I think thats often a point of confusion for folks in terms of how macros work.
Consider this macro
defmodule Mod do
defmacro add(a, b) do
quote do
unquote(a) + unquote(b)
end
end
end
If you haven’t seen macros like this before, it can look pretty magical. It’s not clear that this is an AST template, and that unquote
is a way to interpolate values into that template.
But if you peel back the covers a bit, it actually gets much clearer. There is no rule that a macro must use quote
defmodule Mod do
defmacro add(a, b) do
{:+, [], [a, b]}
end
end
If you put those both in a project you will see that they do the same thing. There are subtle differences not worth going into that make it advantageous to use quote
in general. But when you understand that a macro is just a function that is called at compile time that returns AST, most of the magic goes away.
Something very useful for understanding how elixir AST works in general is to just open up iex and return the result of quote
ing some code for example:
iex(1)> quote do: a + b
{:+, [context: Elixir, imports: [{1, Kernel}, {2, Kernel}]],
[
{:a, [], Elixir},
{:b, [context: Elixir, imports: [{1, IEx.Helpers}]], Elixir}
]}