Elixir:在定义它的同一模块的主体中​​使用宏

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

这是普通的丹药:

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

defmodule Buzz do
  require Fizz
  Fizz.asdf
end

但是,尽管您可以在相同的上下文中引用宏,例如:

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

...您无法在定义它们的同一模块的主体中​​引用宏

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

这会引发 undefined function asdf/0

这个 "problem" 有解决方法吗?有时我可能想使用宏从我正在处理的模块中删除一些样板,并且该宏的功能可能足够具体,不会将其放在另一个模块中。

我们在这里得到 undefined function 错误的原因是因为在编译时,asdf 宏还不存在。

所以我们需要在编译完成之前通知编译器需要一个额外的步骤。

一个选项是 @after_compile 模块回调属性,它允许您在编译后立即调用一些代码以执行代码生成的最后一点。

例如:

defmodule M do
  @after_compile __MODULE__

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

另一种选择是将宏放在 Fizz.Macros 模块中。