Macro variables available in do block?

Hello everyone. I have an issue with macros that I don’t know how to solve.
I have a macro:

defmacro command(expr, do: block) do
  quote do
    def handle_message(unquote(expr), msg) do
      Logger.info("[CONSUMER][EVENT] Recieved command #{unquote(expr)}")
      unquote(block)
    end
  end
end

And I intended using it like this

command "foo" do
  IO.inspect(msg)
end

But I get and error

** (CompileError) lib/myapp.ex:27: undefined function msg/0

The issue is understandable, it seems that it is trying to access msg before macro is expanded.
But how is that possible? Aren’t macros getting expanded on compile time?
Is what I am trying to achieve illegal or am I missing something?

Thanks for your help!

Macros are hygienic, so by default they don’t share their variables with the scope outside of the macro. This is documented here as well as how to work around this:

https://hexdocs.pm/elixir/Kernel.SpecialForms.html#quote/2-hygiene-in-variables

4 Likes