Metaprogramming - Context

Hi Everyone,

I’ve just started learning about metaprogramming in Elixir, and I’m having trouble with one of the key concepts of context.

I wrote up this small gist, where I define a module (UseMacro) that uses another module (DefineMacro), and thereby invokes __using__/1 on DefineMacro.

Can someone help me understand why Line 7, Line 10, and Line 11 resolve to the values that they do (DefineMacro, UseMacro, and DefineMacro, respectively)?

Thank you.


I think I’m ok with Line 7. If I think of a macro as a function, there is nothing there that is surprising.

If I think about quote as returning an AST, then I can see how Line 10 resolves to UseMacro. I can almost “copy and paste” the code returned by quote where I used the use DefineMacro.

I am still very confused on how Line 11 resolves to DefineMacro. If I copied that line into UseMacro, again, in place of use DefineMacro, I would not expect it to resolve to DefineMacro.


By way of analogy, you can think of quote do end as starting a block of text like


unquote is sorta like #{} string interpolation IE

text = "goodbye!"

That will be


Leaving the analogy, quote do does not do anything particularyl magical, you can think of it like a function that takes a block of code and returns AST. You can see this by simply doing: (note the IO.inspect after the quote do end)

defmodule DefineMacro do
  defmacro __using__(_opts) do
    IO.inspect __MODULE__ # DefineMacro

    quote do
      IO.inspect __MODULE__ #UseMacro
      IO.inspect unquote(__MODULE__) #DefineMacro
    |> IO.inspect

what unquote(val) does is simply say "hey, instead of turning this code into AST, simply stick it in there as is.`

Does that help?


That is incredibly helpful! Thank you @benwilson512.


Explaining quote as creating a string and unquote as the interpolation is really clicking. quote starts an AST (a.k.a. string) and unquote puts / interpolates the value straight into the AST.