air*_*led 1 macros function elixir quote
我现在正在学习 Elixir,我真的很困惑quote和unquote。以下是我们如何使用 a 创建具有动态名称的函数macro:
defmacro create_fun(n) do
quote do: def unquote(:"times_#{n}")(a), do: a * 4
end
Run Code Online (Sandbox Code Playgroud)
times_6例如,如果我6作为宏参数传递,它会创建 function 。
现在我不明白的是:这里我们取消引用atom :"times_#{n}"。Elixir 文档说,当你引用一个原子时,它会返回一个原子。所以当我取消引用一个原子时,我也应该找回这个原子。这是真的:
iex(15)> Macro.to_string quote do: unquote(:"times_6")
":times_6"
Run Code Online (Sandbox Code Playgroud)
但是()在引用之后使用会给出这样的结果:
iex(14)> Macro.to_string quote do: unquote(:"times_6")()
"times_6()"
Run Code Online (Sandbox Code Playgroud)
带括号的原子突然就不再是原子了。如果我unquote(:"times_6")用:"times_6"它代替则不起作用:
iex(4)> Macro.to_string quote do: :"times_6"()
** (SyntaxError) iex:4: syntax error before: '('
Run Code Online (Sandbox Code Playgroud)
请问这是怎么回事,没明白
quote&unquote在 Elixir 中的实现方式来自Elixir 元编程指南:
Elixir 程序的构建块是一个包含三个元素的元组。例如,函数调用
sum(1, 2, 3)在内部表示为:Run Code Online (Sandbox Code Playgroud)iex> quote do: sum(1, 2, 3) {:sum, [], [1, 2, 3]}第一个元素是函数名称,第二个元素是包含元数据的关键字列表,第三个元素是参数列表。
模块和方法名称在内部表示为atomsElixir。直接查看调用时生成的底层 Elixir 数据unquote(:"hello")可能unquote(:"hello")()有助于解决这个问题:
iex(27)> quote do: unquote(:"hello")
:hello
iex(28)> quote do: unquote(:"hello")()
{:hello, [], []}
Run Code Online (Sandbox Code Playgroud)
第一个仅返回一个原子,而第二个返回一个Elixir 数据结构(由 3 个元素组成的元组),它表示对具有 0 个参数的方法的函数调用hello。将unquote(:"hello")()转化为hello(),然后将其用作方法。