我现在正在学习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()"
带圆括号的原子突然变成原子。如果我将unquote(:"times_6")
替换为:"times_6"
则不起作用:
iex(4)> Macro.to_string quote do: :"times_6"()
** (SyntaxError) iex:4: syntax error before: '('
拜托,发生了什么,我没有得到它
答案 0 :(得分:4)
quote
& unquote
在Elixir 来自Elixir Metaprogramming Guide:
Elixir程序的构建块是一个有三个的元组 元素。例如,表示函数调用
sum(1, 2, 3)
内部为:iex> quote do: sum(1, 2, 3) {:sum, [], [1, 2, 3]}
第一个元素是函数名称,第二个元素是关键字列表 包含元数据,第三个是参数列表。
模块和方法名称在内部表示为elixir中的atoms
。直接查看调用unquote(:"hello")
和unquote(:"hello")()
时生成的基础elixir数据可能有助于明确这一点:
iex(27)> quote do: unquote(:"hello")
:hello
iex(28)> quote do: unquote(:"hello")()
{:hello, [], []}
第一个只返回一个原子而第二个返回一个 Elixir数据结构(一个由3个元素组成的元组),它代表一个带有0个参数的hello
方法的函数调用。 unquote(:"hello")()
转换为hello()
,然后将其用作方法。