【发布时间】:2017-03-13 01:03:14
【问题描述】:
我现在正在学习 Elixir,我真的对 quote 和 unquote 感到困惑。
下面是我们如何使用 macro 创建具有动态名称的函数:
defmacro create_fun(n) do
quote do: def unquote(:"times_#{n}")(a), do: a * 4
end
它创建函数times_6,例如,如果我将6 作为宏参数传递。
现在我不明白:这里我们取消引用原子:"times_#{n}"。 Elixir 文档说,当你引用一个原子时,它会返回一个原子。所以当我取消引用一个原子时,我也应该取回这个原子。这是真的:
iex(15)> Macro.to_string quote do: unquote(:"times_6")
":times_6"
但是在引用之后使用() 会给出这样的结果:
iex(14)> Macro.to_string quote do: unquote(:"times_6")()
"times_6()"
带括号的原子突然变成不是原子。如果我用:"times_6" 替换unquote(:"times_6"),它就不起作用了:
iex(4)> Macro.to_string quote do: :"times_6"()
** (SyntaxError) iex:4: syntax error before: '('
请问这是怎么回事,我不明白
【问题讨论】:
-
不应该是
do: a * unquote(n)而不是a * 4吗? -
是的。它应该。但这不是重点。这个宏工作正常。我只是试图理解为什么括号有区别。因为一开始我不知道用括号引用/取消引用原子突然返回的不是原子。
-
这里的问题不在于宏,而在于
:"times_6"()。这本身就是一个无效的陈述 -
是的。但是为什么
unquote(:"times_6")()是正确的?unquote(:"times_6")应该返回你:"times_6"
标签: function macros elixir quote