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
Run Code Online (Sandbox Code Playgroud)
但是从其他模块导入,可以成功调用:
defmodule SecondModule do
require DemoMacro
DemoMacro.i_am_macro
end
Run Code Online (Sandbox Code Playgroud)
我该怎么做才能编译第一段代码?
您正在从模块主体调用宏,这意味着在编译阶段.在编译器阶段,此模块内容显然无法访问,因为模块未编译.
将宏移动到一个函数中:
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"
Run Code Online (Sandbox Code Playgroud)
宏内容是在每次宏调用时就地注入的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"
Run Code Online (Sandbox Code Playgroud)