2016-09-17 8 views
0

私はちょうどElixirの基礎を取り上げて、メタプログラミングを楽しみました。私はunless(expression, do: block)部分の意味をなすように見えることはできません関数の引数(マクロ)で `do`構造体を使う

defmodule ControlFlow do 
    defmacro unless(expression, do: block) do 
    quote do 
     if !unquote(expression), do: unquote(block) 
    end 
    end 
end 

:クリス・マッコードの著書では、私たち自身のunless構造を定義する次の例があります。 do:構成の唯一の使用は、関数の本体を短くして1行に圧縮することです。ただし、ここでは、unlessの後に実行されるブロックは、すでに関数の引数の一部です。 do: blockの部分はどのようにここに収まりますか?たぶん私は本当にシンプルなものを見落としていますが、私はそれを指摘して喜んでします。

答えて

1

do: blockは、単純なパターンマッチングで、キーワード引数:doに渡された値を簡単に抽出できます。それはやってと同等です:

defmacro unless(expression, [{:do, block}]) 

、あなたはそれを期待するだけのように振る舞う:あなたはまた、パターンを使用しないようにunlessを書き換えることができます

iex(1)> [do: block] = [do: 123] 
[do: 123] 
iex(2)> block 
123 

の略です

defmacro unless(expression, [do: block]) 

このような一致:

defmodule ControlFlow do 
    defmacro unless(expression, args) do 
    quote do 
     if !unquote(expression), do: unquote(args[:do]) 
    end 
    end 
end 

do:引数がないことを黙って無視するので、これは元のコードと完全には同じではありませんが、サポートするコードを変更するのは簡単です。

+0

素晴らしい!そして、 '{:do、block} 'はタプルであると思いますか?そうであれば、 'arg = {:do、block}'と仮定して、 'args [:do]'としてアクセスされているタプルを思い出しません。あるいは、私は基本的なデータ型を再訪する必要があります! :Pもう少し説明してください。 – dotslash

+2

'args [:do]'は 'args'が最初の項がアトムであるタプルの_list_であるため動作します。これはElixirのキーワードリストとも呼ばれます:http://elixir-lang.org/docs/stable/elixir/ Keyword.html。 – Dogbert

+0

である。今や意味をなさない! :-) – dotslash

関連する問題