使用quote do:
时引用的记录不会转换为包含记录字段的元组:
iex(1)> quote do: is_bitstring("blah")
{:is_bitstring, [context: Elixir, import: Kernel], ["blah"]}
iex(2)> quote do: Computer.new("Test")
{{:., [], [{:__aliases__, [alias: false], [:Computer]}, :new]}, [], [[name: "Test"]]}
iex(3)> quote do: Computer.new("Test")
{{:., [], [{:__aliases__, [alias: false], [:Computer]}, :new]}, [], [[name: "Test"]]}
iex(4)> c = Computer.new("Test")
Computer[name: "Test", type: nil, processor: nil, hard_drives: []]
iex(5)> c
Computer[name: "Test", type: nil, processor: nil, hard_drives: []]
iex(6)> quote do: c
{:c, [], Elixir}
另外,当我尝试在我的代码中执行此操作时:
defmacro computer([do: code]) do
# macro login here
# build computer record based on macro logic
computer = Computer.new(params)
quote do: unquote computer
end
我收到错误:
**(CompileError)elixir / test / lib / computer_dsl_test.exs:带引号的表达式中的元组必须有2或3个项,无效的引用表达式:Computer [name:“”,type:nil,processor:nil,hard_drives: []]
我认为记录只是具有某种包装函数的元组。 Elixir入门指南说明"A record is simply a tuple where the first element is the record module name."
我缺少什么?是否有一个函数我可以调用记录来获取元组表示?我知道raw: true
选项,但我不确定如何在现有记录中使用它。
任何见解?
答案 0 :(得分:6)
记录是元组。您在控制台上看到的输出只是格式化,以便于检查。如果使用raw:true:
检查记录,则可以检查记录是否为元组iex(1)> defrecord X, a: 1, b: 2
iex(2)> x = X.new
X[a: 1, b: 2] # This is formatted output. x is really a tuple
iex(3)> IO.inspect x, raw: true
{X, 1, 2}
可以看出,记录实例实际上是一个元组。你也可以在上面进行模式匹配(虽然我不建议这样做):
iex(4)> {a, b, c} = x
iex(8)> a
X
iex(9)> b
1
iex(10)> c
2
你提到的引用完全不同。它将Elixir表达式转换为AST表示,可以将其注入AST的其余部分,最常见的是宏。引用仅在编译时相关,因此,它甚至无法知道变量中的内容。所以当你说:
quote do: Computer.new("Test")
您得到的结果是Computer.new
函数调用的AST表示。但此时不调用该函数。
答案 1 :(得分:4)
只是在宏定义中阅读错误消息和灵药“获得陈述”,似乎报价的结果具有以下形式:
通常,上面的每个节点(元组)都遵循以下格式:
{tuple | atom,list,list |原子}
The first element of the tuple is an atom or another tuple in the same representation; The second element of the tuple is an list of metadata, it may hold information like the node line number; The third element of the tuple is either a list of arguments for the function call or an atom. When an atom,
这意味着元组代表一个变量。
除了上面定义的节点,还有五个Elixir文字,当引用时返回自己(而不是元组)。他们是:
:sum#=>原子
1.0#=>编号
[1,2]#=>列表
“二进制”#=>字符串
{key,value}#=>具有两个元素的元组
我的猜测是,unquote是quote的反函数,所以它期望作为参数之一的上述形式。计算机记录不是这种情况。
我认为unquote在那里没有必要(虽然我没有尝试理解你的代码的意图......)和那个
defmacro computer([do: code]) do %% why do you need this argument?
quote do: Computer.new
end
应该没问题。