What do Elixir's quote and unquote do (metaprogramming)? 🤔

Notes

If you’ve ever used a use macro (who hasn’t!), or even created your own __using__ macro, you’ll have noticed that we use quote and typically unquote a lot.

def MyModule do
  defmacro __using__(opts) do
    quote do
      # code here
      # unquote(some_var)
    end
  end
end

Why is that?

The __using__/1 macro (and all macros, for that matter) take in and return Elixir’s AST. quote/1 transforms regular Elixir into its AST form. That lets us write code in a nice format, and quote/1 takes care of transforming it for us.

Take a look:

iex> quote do: %{hello: "world"}
# => {:%{}, [], [hello: "world"]}

As you can see, most of Elixir’s AST is represented by 3-tuples (some values like atoms are represented as themselves).

What happens when we define a variable?

iex> quote do: %{hello: name}
# => {:%{}, [], [hello: {:name, [], Elixir}]}

You can see that the variable itself is part of the abstract syntax tree. But what if we want to inject a value instead?

That’s when unquote/1 comes in:

iex> name = "Aragorn"
iex> quote do: %{hello: unquote(name)}
# => {:%{}, [], [hello: "Aragorn"]}

As you can see, we can tell the compiler to inject the value of name instead of transforming name into its AST (which is {:name, [], Elixir}.

Since macros receive and return quoted expressions, we tend to see quote/1 as the last thing we invoke in the macro.

More resources

Want the latest Elixir Streams in your inbox?

    No spam. Unsubscribe any time.