рубиновый хеш как ключ к хешу - PullRequest
4 голосов
/ 22 февраля 2011

Натолкнулся на следующее странное поведение в 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

Ответы [ 2 ]

2 голосов
/ 22 февраля 2011

Ответ заключается в том, что в Ruby 1.8.6 алгоритм хэш-кодирования был сломан для ключей хеш-функции.

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

Edit: Вот пример, который показывает, что 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 сделать это (например, открыть Hash, люди бы это сделали. Это было исправлено в 1.8.7

1 голос
/ 16 апреля 2011

Это исправлено в 1.8.7+, но вы можете сделать патч для обезьяны 1.8.6, чтобы сделать это правильно, например: https://github.com/rdp/sane/blob/master/lib/sane/hash_hashes.rb

...