2

Ruby API says:

The eql? method returns true if obj and other refer to the same hash key.

I changed the hash method for Object:

class Object
 def hash
   1
 end
end

Object.new.hash == Object.new.hash
# => true

Object.new.eql? Object.new
# => false

I don't understand why the second statement returns false; according to Ruby Object API above, it should return true.

Max
  • 21,123
  • 5
  • 49
  • 71
helloyi621
  • 41
  • 5
  • possible duplicate of [What's the difference between equal?, eql?, ===, and ==?](http://stackoverflow.com/questions/7156955/whats-the-difference-between-equal-eql-and) – New Alexandria May 28 '14 at 12:26
  • 1
    I'm not sure what documentation you've been reading, but: "eql? returns true only if obj and other are the same object." http://ruby-doc.org/core-2.1.2/Object.html#method-i-eql-3F – Sergio Tulentsev May 28 '14 at 12:28
  • 1
    That's not what the docs say, and "the same hash key" isn't really relevant to the code you post. – Dave Newton May 28 '14 at 12:28
  • @DaveNewton That is actually what the doc says. Please see my answer. – sawa May 28 '14 at 13:06
  • @sawa Not the docs I'm reading. – Dave Newton May 28 '14 at 13:08
  • I added a link to the question, which is the one I am mentioning. It that different from what you read? – sawa May 28 '14 at 13:10

3 Answers3

2

That's not what the docs say, and "the same hash key" isn't really relevant to the code you post.

hash creates a hash key, with the implication that a.eql?(b) means a.hash == b.hash. That's different than breaking hash and expecting an unmodified eql? to work the way you expect.

eql? must be overridden to provide the semantics you want, e.g., a custom class could override eql? to provide a domain-specific equivalency. The above hash contract implications would still need to be followed if you want other code to work appropriately.

(This is similar to the Java mantra "override hashCode if you override equals, e.g., http://www.xyzws.com/javafaq/why-always-override-hashcode-if-overriding-equals/20.)

Dave Newton
  • 158,873
  • 26
  • 254
  • 302
1

You're creating two new objects, they will never be the same.

a = Object.new
=> #<Object:0x007fd16b35c8b8>
b = Object.new
=> #<Object:0x007fd16b355540>

And I will refer you back to this SO question

Henrik Andersson
  • 45,354
  • 16
  • 98
  • 92
1

This is a documentation bug. You read it correctly, but the documentation is contradictory.

  • On the one hand, the documentation says:

    The eql? method returns true if obj and other refer to the same hash key.

    from which you can expect as you did in your question:

    Object.new.eql? Object.new
    # => true
    
  • On the other hand, it also says:

    For objects of class Object, eql? is synonymous with ==.

    where the definition of == is given as:

    At the Object level, == returns true only if obj and other are the same object.

    It logically follows that:

    For objects of class Object, eql? returns true only if obj and other are the same object.

    from which you should expect:

    Object.new.eql? Object.new
    # => false
    

So the documentation makes contradictory claims. You relied on one of them, and made an expectation, but looking at the actual result, the reality seems to support the second claim.

sawa
  • 165,429
  • 45
  • 277
  • 381
  • Two objects `a`, `b` are ***the same hash key*** if for a hash `h`, `h[a]` and `h[b]` refers to the same object. – Arie Xiao May 28 '14 at 13:49
  • @ArieShaw What are you mentioning about? Are you confusing hash objects with hash function? – sawa May 28 '14 at 13:59
  • 1
    The documentation is definitely confusing in this case. If you read the doc for `Object#hash` it makes it a little clearer that Hash keys in Ruby rely on _both_ `eql?` and `hash`. – Max May 28 '14 at 14:20
  • Are there any bug reports for this documentation bug? – Andrew Grimm May 28 '14 at 23:48
  • @sawa No. I just don't understand why you imply `Object.new.eql? Object.new` from *The eql? method returns true if obj and other refer to the same hash key*. `eql?` method is used in `Hash` to determine the equality of the keys. If two object `a`, `b` has the same `.hash`, for a Hash `h`, `h[a]` and `h[b]` may refer to the same bucket in the underlying implementation. However, they refer to the same value if and only if `a.hash == b.hash && a.eql? b`. (Ruby may have special treatment with `String` and `Symbol`) http://ruby-doc.org/core-2.1.2/Object.html#method-i-hash – Arie Xiao May 29 '14 at 02:51
  • @AndrewGrimm I haven't reported any. You can, if you want. – sawa May 29 '14 at 03:09