🎓 A1Learner
🔍
0 of 46 lessons completed

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?