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とかで聞くようにしよう。