Elixir Macros
A macro is code that receives code and returns code. The returned code is what finally runs.
A macro returns new code
The greet macro builds a greeting from the name it is given. A second module calls it.
defmodule GreeterMacro do
defmacro greet(name) do
quote do: "Hello, " <> unquote(name)
end
end
defmodule GreeterCaller do
require GreeterMacro
def run do
GreeterMacro.greet("Ana")
end
end
IO.puts(GreeterCaller.run())A macro sees the code, not the value
Show returns the text of 1 + 2, not the number 3.
defmodule ShowMacro do
defmacro show(code) do
Macro.to_string(code)
end
end
defmodule ShowCaller do
require ShowMacro
def run do
ShowMacro.show(1 + 2)
end
end
IO.puts(ShowCaller.run())A macro can delay work
The body runs only when the condition is true.
defmodule LazyMacro do
defmacro run_when(condition, body) do
quote do
if unquote(condition), do: unquote(body)
end
end
end
defmodule LazyCaller do
require LazyMacro
def run do
LazyMacro.run_when(false, "ran")
end
def run_true do
LazyMacro.run_when(true, "ran")
end
end
IO.inspect(LazyCaller.run())
IO.puts(LazyCaller.run_true())Example
defmodule LabelMacro do
defmacro labelled(code) do
quote do
{unquote(Macro.to_string(code)), unquote(code)}
end
end
end
defmodule LabelCaller do
require LabelMacro
def run do
LabelMacro.labelled(2 + 3)
end
end
IO.inspect(LabelCaller.run())Key points
- Macro: a macro is a definition that works on code, not on values.
- Use defmacro to define a macro inside a module.
- Input: a macro receives the code as written, before it is evaluated.
- Output: a macro returns code that replaces the macro call.
- Use a macro to add new syntax or to delay work until it is needed.
In this example, the labelled macro receives 2 + 3 as code, builds a pair of its text and its result, and the caller prints that pair.
Note
a macro call looks like a function call, but its argument is not evaluated first.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
What does a macro receive from its caller?