简体   繁体   中英

ruby hash as key to a hash

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:

 class Hash
    def hash
       raise
    end
 end

 {1=>1}.hash
 RuntimeError: 
from (irb):12:in `hash'
from (irb):17

 h = {1=>2}
 {1=>2}
 h[1]
 2

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

这在1.8.7+中得到修复,但是您可以使用补丁1.8.6做正确的操作,例如: https//github.com/rdp/sane/blob/master/lib/sane/hash_hashes.rb

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM