我有以下代码段:
defmodule Play do
defmacro mobile(expr) do
IO.puts "I will compile"
quote do
IO.puts "#{inspect unquote(expr)}"
unquote(expr)
end
end
end
defmodule Run do
import Play
def run do
IO.puts "Execute macro"
mobile(2+2)
end
end
当我编译这个文件时,我有以下输出
iex(46)> c "playground.exs"
I will compile
[Run, Play]
正如你所看到的,elixir编译宏但引用块是不受影响的。 所以,当我运行以下代码片段时:
iex(47)> import Run
nil
iex(48)> Run.run
Execute macro
4
4
宏中的引用表达式将按预期执行。
现在我删除了运行模块
defmodule Play do
defmacro mobile(expr) do
IO.puts "I will compile"
quote do
IO.puts "#{inspect unquote(expr)}"
unquote(expr)
end
end
end
编译文件
iex(49)> c "playground.exs"
playground.exs:1: warning: redefining module Play
[Play]
这里的文字I will compile
?
之后,导入模块
iex(50)> import Play
nil
执行它
iex(51)> Play.mobile 2 + 2
I will compile
4
4
瞧,文字出现了。
当我将宏导入模块并导入shell时有什么区别?为什么我没有将文本I will compile
作为第二个例子?
答案 0 :(得分:2)
编译定义它的模块(Play
)时,不执行宏。它是在编译调用它的模块时执行的。你只会看到"我会编译"当宏被执行时,它应该说"我将执行。"
在第一个示例中,在编译Run
模块时执行宏。
在第二个示例中,当repl编译您提供的代码行时,将执行宏。
如果将Run
模块拆分为自己的文件,则可以自行进一步验证。编译Play
然后编译Run
,看看你什么时候得到"我将编译"消息。