ハッシュを再計算するHash#rehash
RubyでHashのKeyにArrayやHashを使ってみたところ、値が取り出せなくなった。
irb(main):001:0> a = ["a","b"] => ["a", "b"] irb(main):002:0> c = ["c","d"] => ["c", "d"] irb(main):003:0> h = {a => 100, c => 200} => {["a", "b"]=>100, ["c", "d"]=>200} irb(main):004:0> h[a] => 100 irb(main):005:0> h[["a","b"]] => 100 irb(main):006:0> a[0] = "e" => "e" irb(main):007:0> h[a] => nil irb(main):008:0> h => {["e", "b"]=>100, ["c", "d"]=>200} irb(main):009:0> a => ["e", "b"] irb(main):010:0> h.rehash => {["e", "b"]=>100, ["c", "d"]=>200} irb(main):011:0> h[a] => 100 irb(main):012:0>
↑の例では6行目でキーにしているオブジェクトaの値を書き換えたところ、7行目でオブジェクトaをキーにしているハッシュがnilを返すようになる。
しかしハッシュの中身を見てみると、一見正しいように見えるが、このキーにはアクセスできない。
irb(main):012:0> h[a] => 100 irb(main):013:0> a[0] = 1 => 1 irb(main):014:0> h[a] => nil irb(main):015:0> h => {[1, "b"]=>100, ["c", "d"]=>200} irb(main):016:0> h[a] = 100 => 100 irb(main):017:0> h => {[1, "b"]=>100, [1, "b"]=>100, ["c", "d"]=>200} irb(main):018:0> h.rehash => {[1, "b"]=>100, ["c", "d"]=>200}
一見同じキーが2個出来たりする。
こんな風に、オブジェクトをキーにしていてオブジェクトが書き換わった場合はrehashをすると、正しくアクセスできるHashに戻るようだ。
irb(main):027:0> h => {[2, "b"]=>300, [2, "b"]=>100, ["c", "d"]=>200} irb(main):028:0> h.rehash => {[2, "b"]=>100, ["c", "d"]=>200}
同じキーで別の値を持ってる状態でrehashすると、片方は消えた。
http://www.ruby-lang.org/ja/man/html/Hash.html#rehash
http://www.ruby-doc.org/docs/ProgrammingRuby/html/ref_c_hash.html#Hash.rehash