Rubyの多重代入におけるto_aとto_aryの挙動
先日のエントリでRubyの多重代入についてふれたのだが、教科書によってto_aryが呼ばれると書いてあったりto_aが呼ばれると書いてあったりで、なにが本当なのか分からなくなった。
回答らしきもの
調べてみたら、こちらに回答らしきものがあった。
OK, to_a means an explicit array conversion, so it should not be used
for implicit conversion a in "*y = x". On the other hand, I consider
"*x" as a form of explicit conversion, i.e. shorthand for "*(x.to_a)",
so that the current 1.9 behavior is intentional.
matz.
どうやら、Ruby1.9においては、暗黙的なコンテキストではto_aryが呼ばれ、明示的なコンテキストではto_aが呼ばれるようだ。
1.9.2で試してみた
class C def to_ary; [1,2]; end def to_a; [3,4]; end end c = C.new a, b = c # 暗黙的 d, e = *c # 明示的 puts a, b # 1,2 puts d, e # 3,4
確かに暗黙的なコンテキスト(a,b = c)ではto_aryが呼ばれており、明示的なコンテキスト(d,e = *c)ではto_aが呼ばれていることが分かる。ただ、これはto_aryとto_aの両方が定義されている場合の挙動であり、片方の場合には挙動が違った。上記においてto_aryのみを定義した場合、明示的コンテキストにおいてもto_aryが呼ばれる(to_aの代わりに)。しかしto_aのみを定義した場合は、暗黙的コンテキストにおいては通常の多重代入が行われる(to_aryの代わりにto_aが呼ばれることはない)。結構ややこしい。
1.8.7でも試してみた。
class C def to_ary; [1,2]; end def to_a; [3,4]; end end c = C.new a, b = c # 暗黙的 d, e = *c # 明示的 puts a, b # 1,2 puts d, e # 1,2
さらにややこしいことに、1.8.7の場合、1.9.2とは挙動が違った。to_aryとto_a両方が定義されていると、暗黙的でも明示的でもto_aryが呼ばれる。片方だけ定義された場合でいうと、to_aryのみが定義されている場合、暗黙的でも明示的でもto_aryが呼ばれる。一方to_aのみが定義されている場合は、暗黙的コンテキストでは通常の多重代入が行われ、明示的コンテキストにおいてはto_aが呼ばれる。
まとめ
すごく混乱したので、まとめておく。あまりこの違いで悩むことは無いだろうけど。。。
Ruby バージョン | 暗黙的コンテキスト | 明示的コンテキスト |
---|---|---|
1.9.2 | to_ary | to_a(なければto_ary) |
1.8.7 | to_ary | to_ary(なければto_a) |