[Elixir]defmacroに2つの要素を持つTupleを与えるとき、例外的にTupleがそのままASTとして使われる

ex_parameterizedを修正していたときに遭遇した振る舞い。

以下の通り、簡単な defmacro でマクロを定義していたら、 Example.a(do: {1, 2}) のように、この場合だけ意図しない出力が得られました。

defmodule Example do
  defmacro a(input) do
    IO.inspect input
  end
end

defmodule MySample do
  require Example

  Example.a(do: {1})       # [do: {:{}, [line: 10], [1]}]
  Example.a(do: {1, 2})    # [do: {1, 2}]
  Example.a(do: {1, 2, 3}) # [do: {:{}, [line: 12], [1, 2, 3]}]
end

これ、 Example.a(do: {1, 2}) の出力として [do: {:{}, [line: 11], [1, 2]}] が得られないといけない、と思って 聞いてみた ら、これは以下の通り問題ないみたいですね。

Quote literals

Besides the tuple described above, Elixir has a few literals that when quoted return themselves. They are:

  :sum         #=> Atoms
  1            #=> Integers
  2.0          #=> Floats
  [1, 2]       #=> Lists
  "strings"    #=> Strings
  {key, value} #=> Tuples with two elements
  

つまるところ、この defmacro の中身の Example.a(do: {1, 2}) は、 {key, value} のtupleに該当するから [do: {1, 2}] が得られるのは仕様として正しい、という。

なるほど。。。AtomsやIntergerとかとか、基礎的なリテラルは想定していた通りなのですが、 Tuple が要素数2のときだけ例外だったのですね…


ElixirのGithubのissueで聞いてしまっていたのですが、StackOverflowやSlackなんかで聞いた方が良かったのですね。見逃していた。。。次はSlackとかで聞くようにしよう。

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s