Skip to content

Latest commit

 

History

History
62 lines (48 loc) · 2 KB

File metadata and controls

62 lines (48 loc) · 2 KB

20.4 値の注入のためのバインディングの利用

quoteブロックに値を注入する方法

  • unquote関数を使う
  • バインディングを使う

バインディング:

  • 変数名と値のキーワードリスト
  • quoteにバインディングを渡すとquoteのボディの中の変数が設定される
goh@goh% iex macros/macro_no_bindin_prep.exs
Erlang/OTP 21 [erts-10.1.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe] [dtrace]

some_name

マクロはコンパイル時に実行される マクロが呼ばれた時点では、 each の繰り返しは実行されていないため、渡すべき値がない

goh@goh% iex macros/macro_no_binding.exs
Erlang/OTP 21 [erts-10.1.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe] [dtrace]

** (CompileError) macros/macro_no_binding.exs:11: invalid syntax in def x1()
    (elixir) lib/enum.ex:765: Enum."-each/2-lists^foreach/1-0-"/2
    (elixir) lib/enum.ex:765: Enum.each/2
    macros/macro_no_binding.exs:11: (module)

バインディングの効果

  • name の現在の値をquoteブロックで利用可能になる
    内部表現はキーワードリストになっているので、 name のキー :name を指定して name の値を取り出している
  • bind_quoted: により、 unquote の実行が遅延される
    bind_quotedquote された(内部表現化された)コード片を取る
goh@goh% iex macros/macro_binding.exs
Erlang/OTP 21 [erts-10.1.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe] [dtrace]

fred

`Macro.escape(expr, opts)

  • expr: 式
  • opts: オプション

再帰的に値をエスケープする
これにより抽象構文木に挿入可能になる
Kernel.SpecialForms.quote/2 との違いは「変数に格納された値」の処理の仕方

> value = {:a, :b, :c}
{:a, :b, :c}
> Macro.escape(value)
{:{}, [], [:a, :b, :c]}
> quote do: value
{:value, [], Elixir}
> quote do: unquote(value)
{:a, :b, :c}