2017-01-20 2 views
1

私はElixirを学んでいます(Ruby、JSでいくつかのエキスパートを持っています)。興味深い質問があります。好奇心から、機能プログラミングのより良い理解のために。 documentationからなぜ、エリクシル 'if'マクロがタプル{:do、 "true part"}にマッチした変数を受け入れないのですか?

if(condition, clauses) 

は、if/2マクロを提供します。 このマクロは、最初の引数が条件であり、2番目の引数がキーワードリストであると想定しています。

if(true, [do: "true stuff", else: "false stuff"]) # => "true stuff" 

をそして、このラインは完璧に働いている:

言い換えれば、私は書くことができます。 OK。

しかし、私が知っている限り、キーワードリストはタプルのリストです。だから私は試しました:

if(true, [{:do, "true stuff"}, {:else, "false stuff"}]) # => "true stuff" 

まだ動作しています!

良い。次のステップを実行します:

var = "true stuff" 
if(true, [{:do, var}, {:else, "false stuff"}]) # => "true stuff" 

ニース。さあ、夢中に!

var = {:do, "true stuff"} 
if(true, [var, {:else, "false stuff"}]) 

** (ArgumentError) invalid or duplicate keys for if, only "do" and an optional "else" are permitted 
    (elixir) lib/kernel.ex:2569: Kernel.build_if/2 
    (elixir) expanding macro: Kernel.if/2 
      iex:18: (file) 

おっと!

そして、私たちは単に「IEX」すべてがOKですでそれをしようとした場合:

var = {:do, "true stuff"} 
[var] # => [do: "true stuff"] 

なぜエリクサーの「場合は、」マクロは、この「タプルを食べていいの」「認識」していませんか?

このようなものは目的によって作られましたか?

答えて

3

ifマクロはmacro, accepting a keyword listパラメータです。 (4行以下)のみdoキーが提示され、両方のdoelseが提示されている

他のすべての呼び出しは直接句に一致しないあなたが見ているraises an exceptionこと、:許さ2つの可能なバリエーションがあります。

今度は、リストがどのように動作するかのキーワードを理解してみましょう:

iex> quote do: [a: 42] 
[a: 42] 
iex> quote do: [{:a, 42}] 
[a: 42] 

彼らは同じです!それは、すべてのマクロ展開の前に扱われます理由です、1はそれでブロックを渡す可能性があるため

iex> var = [a: 42] 
iex> quote do: var 
{:var, [], Elixir} 

do句は、エリクサーで特別な意味を持っており、一つはさえキーワードを埋め込むことはできません。しかし、誰もあなたのためのVARをデコードしないだろうあなたが別のマクロで試したのと同じリスト。

+0

「クォート」を私に指摘してくれてありがとう@mudasobwa。私はElixir [それについての文書](http://elixir-lang.org/getting-started/meta/quote-and-unquote.html)をチェックしました。次のステップでは、[documentation](http://elixir-lang.org/getting-started/meta/macros.html)にマクロをチェックしました。次の行を見つけてください: "...関数呼び出しの引数は関数を呼び出す前に評価されます。しかし、マクロは引数を評価しません。代わりに、彼らは引用された式として引数を受け取ります... "この言葉とあなたの答えは一緒に私の質問を私に説明しています。 –

関連する問題