2013-10-30 32 views
1

當使用quote do:記錄引述不會轉換爲包含記錄字段的元組:Elixir報價記錄(把它變成一個元組)並保存數據?

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: tuples in quoted expressions must have 2 or 3 items, invalid quoted expression: 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

您的代碼也不適用於記錄。 「計算機」宏的用途是什麼? –

+0

@RamonSnir我從宏中刪除了一些代碼,以使它更清楚我所問的內容。我在我的問題中添加了對代碼的評論,以使其更清晰。 – Stratus3D

回答

6

記錄是元組。您在控制檯上看到的輸出只是格式化,以便於檢查。您可以檢查記錄的元組,如果你使用原始檢查他們:真:

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表示。但是此時不調用該函數。

+0

爲什麼要避免模式匹配記錄? –

+1

因爲你依靠記錄的結構和內部表示。如果您修改結構(例如通過添加字段),代碼將會中斷。如果您重新命名記錄,代碼將會中斷。如果Elixir更改記錄的內部表示形式,代碼將會中斷。 您應該使用正確的記錄模式匹配,例如, 'X [a:1] = x'。這應該能夠在結構性變化中倖存下來,並且可能會發生內部表徵變化 – sasajuric

4

只是閱讀似乎報價結果的形式是錯誤消息和靈藥的宏定義「使用說明」:

In general, each node (tuple) above follows the following format:

{ tuple | atom, list, list | atom }

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, 

it means the tuple represents a variable.

Besides the node defined above, there are also five Elixir literals that when quoted return themselves (and not a tuple). They are:

:sum #=> Atoms

1.0 #=> Numbers

[1,2] #=> Lists

"binaries" #=> Strings

{key, value} #=> Tuples with two elements

我的猜測是,所享有的報價的反轉功能,所以它期望作爲上述形式之一的論據。這不是計算機記錄的情況。

我覺得引文結束是沒有必要存在(雖然我沒有試着去了解你的代碼...)的意圖和

defmacro computer([do: code]) do %% why do you need this argument? 
    quote do: Computer.new 
end 

應該沒問題。

+1

「我的猜測是,引號是引用的反函數,所以它期望作爲上述形式之一的參數,這不是計算機記錄的情況。」 - >這是完全正確的。 您無法取消記錄,因爲它不是有效的AST。如果你想向AST注入一條記錄,你首先需要用Macro.escape/1來轉義它。 –

相關問題