Рубиновый хеш как ключ к хешу
Столкнулся со следующим странным поведением в 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.
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 ответа
Ответ заключается в том, что в 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 сделать это (например, открытие Hash
люди будут делать это. Это было исправлено в 1.8.7
Это исправлено в 1.8.7+, но вы можете сделать исправление 1.8.6, чтобы сделать это правильно, например: https://github.com/rdp/sane/blob/master/lib/sane/hash_hashes.rb