Here’s one example where (4) is very useful. ie Defering unquote
to an expansion phase after the macro is inserted in the calling place.
This example applies two concepts:
-
Module attributes are evaluated after macro expansion. Which means you can’t evaluate them in a macro. So they need to be evaluated after the AST returned by the macro is inserted into the caller.
-
Special forms are also macros. So we need to help the compiler understand when to expand an
unquote
- in the macro or in the caller.
defmodule MyMacros do
@moduledoc """
Define a functions based upon a list of values
"""
defmacro with_vals(values) do
quote bind_quoted: [values: values] do
# `for` introduces its own macro context in which
# we want to unquote. So the unquote needs to be
# deferred until a later expansion in the calling
# site. `bind_quoted: [values: values]` means that
# referring to `values` in the quote body is automatically
# unquoted. And any `unquote` is *not* evaluated in the
# macro context but will be evaluated *after* the
# returned AST is inserted into the calling site.
for val <- values do
def n(unquote(val)), do: unquote(val + 2)
end
end
end
end
defmodule MyModule do
require MyMacros
@all_vals [1,2,3,4,5,6]
# defines 6 function clauses for the
# function `n`.
MyMacros.with_vals(@all_vals)
end
In summary, here is a case where the entire for
expression - including the unquote(...)
is inserted unmodified into the calling site. Since for
, def
, defmodule
are all themselves macros, its completely ok to unquote
in their contexts. These cases are referred to as unquote fragments