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

时间:2016-07-29 15:56:22

标签: macros metaprogramming elixir

这是常见的灵药:

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

是否有针对此问题的解决方法"?有时我可能想使用宏从我正在处理的模块中删除一些样板,并且该宏的功能可能非常具体,不能将其放在另一个模块中。

1 个答案:

答案 0 :(得分:1)

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

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

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

例如:

defmodule M do
  @after_compile __MODULE__

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

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