Rubyの多次元配列は要注意

これはRubyに限った話では無いのですが、何回もこれが原因のエラーを出しているので自戒の意味を込めてメモ。

初期化するときはブロックを使う

これ鉄則。

irb(main):003:0> aa = Array.new 2, Array.new(2)
=> [[nil, nil], [nil, nil]]
irb(main):004:0> aa[0][0] = 1
=> 1
irb(main):005:0> aa
=> [[1, nil], [1, nil]]

ついついこういうことをやりがちですが*1、ブロックを使うのが正解です。

irb(main):007:0> aa = Array.new(2) { Array.new(2) }
=> [[nil, nil], [nil, nil]]
irb(main):008:0> aa[0][0] = 1
=> 1
irb(main):009:0> aa
=> [[1, nil], [nil, nil]]

一方、JavaScriptでは…

実は大丈夫だったりします。

> aa = new Array(2, new Array(2))
[2, Array[2]]
> aa = new Array(2)
[undefined × 2]

引数が1つで数値の時だけ、指定要素数のundefinedな配列を作るので、Rubyのような事故は起きません。どちらが良いかは微妙なところですが、JavaScript式の方が個人的には安心です*2

*1:私だけ?

*2:Rubyはブロック使えるから、利便性も落とさないし