简体   繁体   中英

Elixir: use macro in the body of same module that defined it

This is common elixir:

defmodule Fizz do
  defmacro asdf, do: IO.puts("asdf")
end

defmodule Buzz do
  require Fizz
  Fizz.asdf
end

However, although you can reference macros in the same context like:

defmodule Fizz do
  # ...
  defmacro asdf_qwer, do: asdf && IO.puts("qwer")
end

... you can't reference macros in the body of the same module that defined them :

defmodule Fizz do
  defmacro asdf, do: IO.puts("asdf")
  asdf
end

This raises undefined function asdf/0 .

Is there a workaround for this "problem"? Sometimes I may want to use macros to remove some boilerplate from the module I'm working on, and that macro's functionality may be specific enough not to put it in another module.

The reason that we're getting undefined function errors here is because at compile time, the asdf macro does not yet exist.

So we need to notify the compiler that an extra step is required just before compilation is finished.

One option is the @after_compile module callback attribute which lets you invoke some code just after compilation in order to perform a final bit of code generation.

For example:

defmodule M do
  @after_compile __MODULE__

  def __after_compile__(env, _bytecode) do
    IO.inspect env
  end
end

Another option is to put your macros in a Fizz.Macros module.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM