Came across the following weird behaviour in ruby 1.8.6, in 1.8.7 it seems to be working correctly. Does anyone know what would have caused this?
h = {}
key_1 = {1 => 2}
key_2 = {1 => 2}
h[key_1] = 3
p key_1 == key_2 # => true
p h.has_key?(key_2) # => expect true, get false, wtf?
I had thought that it would be caused by the implementation of the hash method on the Hash class.
p [key_1.hash, key_2.hash] # => [537787070, 537787060] (different)
but even if I override the hash method of Hash
class Hash
def hash
return self.keys.hash + self.values.hash
end
end
p [key_1.hash, key_2.hash] # => [8,8] (same
p h.has_key?(key_2) # => false
codepad link to online ruby 1.8.6 interpreter results: http://codepad.org/7nCYMP4w
The answer is because in Ruby 1.8.6 the hash coding algorithm was broken for hash keys.
http://paulbarry.com/articles/2009/09/14/why-rails-3-will-require-ruby-1-8-7
Edit: Here is an example that shows that ruby does not call .hash internally:
Ruby 1.8.6 is broken in this respect, and if there were a pure Ruby way to do it (such as opening
Hash
, people would do it. It was fixed in 1.8.7