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
模块中。
这是普通的丹药:
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
模块中。