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

nic*_*oga 5 macros metaprogramming elixir

这是常见的灵药:

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

defmodule Buzz do
  require Fizz
  Fizz.asdf
end
Run Code Online (Sandbox Code Playgroud)

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

defmodule Fizz do
  # ...
  defmacro asdf_qwer, do: asdf && IO.puts("qwer")
end
Run Code Online (Sandbox Code Playgroud)

...您不能在定义它们的同一模块的主体中​​引用宏:

defmodule Fizz do
  defmacro asdf, do: IO.puts("asdf")
  asdf
end
Run Code Online (Sandbox Code Playgroud)

这引起了提升undefined function asdf/0.

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

小智 1

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

因此,我们需要在编译完成之前通知编译器需要执行额外的步骤。

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

例如:

defmodule M do
  @after_compile __MODULE__

  def __after_compile__(env, _bytecode) do
    IO.inspect env
  end
end
Run Code Online (Sandbox Code Playgroud)

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