1

レコードを使用して引用する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 Getting Started ガイド"A record is simply a tuple where the first element is the record module name."には、足りないものがありますか? と記載されています。タプル表現を取得するためにレコードで呼び出すことができる関数はありますか? オプションは知っていraw: trueますが、既存のレコードでそれを使用する方法がわかりません。

洞察はありますか?

4

2 に答える 2

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 表現です。ただし、この時点では関数は呼び出されません。

于 2013-10-31T09:05:32.577 に答える
4

エラーメッセージとエリクサーがマクロ定義で「述べられている」を読むだけで、引用の結果が次の形式になっているように見えます。

一般に、上記の各ノード (タプル) は次の形式に従います。

{ タプル | アトム、リスト、リスト | 原子 }

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, 

タプルが変数を表すことを意味します。

上記で定義されたノードに加えて、引用されたときに (タプルではなく) 自分自身を返す 5 つの Elixir リテラルもあります。彼らです:

:sum #=> アトム

1.0 #=> 数字

[1,2] #=> リスト

"binaries" #=> 文字列

{key, value} #=> 2 つの要素を持つタプル

私の推測では、unquote は quote の逆関数であるため、上記の形式のいずれかを引数として期待します。これは、コンピュータ レコードには当てはまりません。

そこでは引用符を外す必要はないと思います(コードの意図を理解しようとはしませんでしたが...)そして

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

大丈夫なはず。

于 2013-10-31T09:53:46.527 に答える