Reputation: 723
I'm on Ruby 2.2.1 and have the following situation:
a = ... # some object
h = ... # some hash
p h.size #=> 1
p h.keys.first.hash == a.hash #=> true
p h.keys.first.eql?(a) #=> true
p h.has_key?(a) #=> false
How is this possible? I thought that the hashes matching and eql?
returning true were the only conditions for keys to be considered equal.
Hash
count for nothing in this situation.
class A
attr_reader :x
def initialize(x)
@x = x
end
MY_HASH = { A.new(5) => 'foo' }
def ==(other)
@x == other.x
end
alias_method :eql?, :==
def hash
@x
end
end
a = A.new(5)
h = A::MY_HASH
p h.size #=> 1
p h.keys.first.hash == a.hash #=> true
p h.keys.first.eql?(a) #=> true
p h.has_key?(a) #=> false
Upvotes: 2
Views: 223
Reputation: 13901
At the time when you create MY_HASH
the new hash
function of A
is not yet defined so MY_HASH
will use the default one when creating an index of it's values. When you later define a new hash function it will change how the objects are hashed BUT NOT AUTOMATICALLY update the index in the already existing Hash MY_HASH
.
You solve this my initializing MY_HASH
after you have defined the new hash
method for class A
or by running MY_HASH.rehash
p h.has_key?(a) #=> false
A::MY_HASH.rehash
p h.has_key?(a) #=> true
Upvotes: 3