Elixir 中的引用函数名称

air*_*led 1 macros function elixir quote

我现在正在学习 Elixir,我真的很困惑quoteunquote。以下是我们如何使用 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)

请问这是怎么回事,没明白

She*_*yar 5

这就是quote&unquote在 Elixir 中的实现方式

来自Elixir 元编程指南

Elixir 程序的构建块是一个包含三个元素的元组。例如,函数调用sum(1, 2, 3)在内部表示为:

iex> quote do: sum(1, 2, 3)
{:sum, [], [1, 2, 3]}
Run Code Online (Sandbox Code Playgroud)

第一个元素是函数名称,第二个元素是包含元数据的关键字列表,第三个元素是参数列表。


模块和方法名称在内部表示为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(),然后将其用作方法。