LoginSignup
4
4

More than 5 years have passed since last update.

Ruby で Hash.new に空配列をうっかり渡して怪我した

Posted at

ハッシュでvalueの初期値を空配列にしようとしてうっかりやってしまった。
欲しかったのは、単純化すると以下のようなハッシュ。

h[0] # => [0]
h[1] # => [0, 1]
h[2] # => [0, 1, 2]
h[3] # => [0, 1, 2, 3]
h['a'] # => []

実際に書いたコードは以下のような感じ。

h = Hash.new([])
(0..9).each do |key|
  h[key] << (0..key).to_a
end

実際の動作はというと、

> h = Hash.new([])
=> {}
> (0..9).each do |key|
  h[key] << (0..key).to_a
end
=> 0..9
> h
=> {}
> h.keys
=> []
> h.values
=> []
> h.empty?
=> true
> h[0]
=> [[0],
 [0, 1],
 [0, 1, 2],
 [0, 1, 2, 3],
 [0, 1, 2, 3, 4],
 [0, 1, 2, 3, 4, 5],
 [0, 1, 2, 3, 4, 5, 6],
 [0, 1, 2, 3, 4, 5, 6, 7],
 [0, 1, 2, 3, 4, 5, 6, 7, 8],
 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]]
> h[9]
=> [[0],
 [0, 1],
 [0, 1, 2],
 [0, 1, 2, 3],
 [0, 1, 2, 3, 4],
 [0, 1, 2, 3, 4, 5],
 [0, 1, 2, 3, 4, 5, 6],
 [0, 1, 2, 3, 4, 5, 6, 7],
 [0, 1, 2, 3, 4, 5, 6, 7, 8],
 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]]
> h['a']
=> [[0],
 [0, 1],
 [0, 1, 2],
 [0, 1, 2, 3],
 [0, 1, 2, 3, 4],
 [0, 1, 2, 3, 4, 5],
 [0, 1, 2, 3, 4, 5, 6],
 [0, 1, 2, 3, 4, 5, 6, 7],
 [0, 1, 2, 3, 4, 5, 6, 7, 8],
 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]]

マニュアルでnew(ifnone = nil)をみると、

空の新しいハッシュを生成します。ifnone はキーに対 応する値が存在しない時のデフォルト値です。設定したデフォルト値はHash#defaultで参照できます。
デフォルト値として、毎回同一のオブジェクトifnoneを返します。 それにより、一箇所のデフォルト値の変更が他の値のデフォルト値にも影響します。

http://docs.ruby-lang.org/ja/2.0.0/class/Hash.html

Hashにデフォルト値を与えるのは良くないと考えてなかったので、あまり使っていなかったが、気をつけよう。

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4