4

在 ruby​​ 1.8.6 中遇到以下奇怪的行为,在 1.8.7 中它似乎工作正常。有谁知道是什么原因造成的?

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?

原以为是在 Hash 类上实现了 hash 方法造成的。

p [key_1.hash, key_2.hash] # => [537787070, 537787060] (different)

但即使我覆盖了 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

在线 ruby​​ 1.8.6 解释器结果的键盘链接:http: //codepad.org/7nCYMP4w

4

2 回答 2

2

答案是因为在 Ruby 1.8.6 中,散列键的散列编码算法被破坏了。

http://paulbarry.com/articles/2009/09/14/why-rails-3-will-require-ruby-1-8-7

编辑:这是一个示例,显示 ruby​​ 不会在内部调用 .hash :

 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 在这方面是有问题的,如果有纯 Ruby 的方式来做(比如 open Hash,人家会做的。在 1.8.7 中修复了)

于 2011-02-22T08:27:52.253 回答
1

This is fixed in 1.8.7+ but you can monkey patch 1.8.6 to do it right, too ex: https://github.com/rdp/sane/blob/master/lib/sane/hash_hashes.rb

于 2011-04-15T20:04:20.430 回答