defmodule DemoMacro do
defmacro i_am_macro do
quote do
# ……
end
end
i_am_macro # (CompileError) example.exs:10: undefined function i_am_macro/0
end
但是从其他模块导入的,可以成功调用:
defmodule SecondModule do
require DemoMacro
DemoMacro.i_am_macro
end
我应该怎么做才能使第一段代码编译?
答案 0 :(得分:5)
您正在从模块主体中调用宏 ,这意味着在编译阶段。在编译器阶段,该模块的内容显然无法访问,因为该模块尚未编译。
将宏移至函数中
defmodule DemoMacro do
defmacro i_am_macro do
quote do
IO.puts "Inside a macro"
end
end
def test_macro(), do: i_am_macro()
end
DemoMacro.test_macro()
#⇒ "Inside a macro"
宏内容是在每个宏调用中注入的AST。在编译阶段,您可以使用已编译的Elixir代码。了解编译阶段和运行时之间的差异需要一定的思想转变,这主要是因为在两个阶段中,我们都使用相同的Elixir语法。但事实是,Elixir是一种编译语言,除非将其编译为BEAM,否则无法使用该代码。
您还可以在@after_compile
回调中使用宏,在编译阶段,即BEAM模块可用(已编译)之后:
defmodule DemoMacro do
defmacro i_am_macro do
quote do
IO.puts "Inside a macro"
end
end
@after_compile __MODULE__
def __after_compile__(env, _bytecode) do
i_am_macro()
end
end
#⇒ immediately prints "Inside a macro"