h unquote
说“从宏内部取消引用给定的表达式。”
但是,我刚刚看到unquote
可以在宏外部使用的方式。
defmodule Example do
x = 4
def foo do
unquote(x)
end
x = 5
def bar do
x = 4
"#{unquote(x)}, #{x}"
end
end
IO.puts Example.foo #=> 4
IO.puts Example.bar #=> "5, 4"
这是unquote
相同还是不同?这是一个功能还是一个bug? (它似乎与"temporary storage" purpose of module attributes重叠。)
为什么我可以在宏unquote
之外拨打quote
?
答案 0 :(得分:3)
这是有效的,因为def
本身是一个用defmacro
实现的宏,并返回一个带引号的表达式。因此,虽然看起来你不在引用的表达式中,因为你没有调用quote
,实际上你是。
还有其他地方也适用,例如在ExUnit测试中(同样是因为test
宏使用def
来定义函数。https://github.com/elixir-lang/elixir/blob/928302a912e397917be957142a9837ae58610207/lib/ex_unit/lib/ex_unit/case.ex#L256
答案 1 :(得分:3)
最简单的答案是模块中的所有内容都在隐式quote
内。
特别是这在defmodule
的定义中完成(这只是一个常规宏):https://github.com/elixir-lang/elixir/blob/master/lib/elixir/lib/kernel.ex#L3008
为什么需要这个? Elixir编译器适用于AST,获取AST的唯一方法是引用代码。
免责声明:这是我对正在发生的事情的理解。关于为什么这样做的真相可能会有所不同。