-1

This is confusing. Why does this happen?

2.0 == 2   # => true
2.0.eql? 2 # => false
sawa
  • 165,429
  • 45
  • 277
  • 381
aarti
  • 2,815
  • 1
  • 23
  • 31
  • It would be inconvenient if it didn't. – sawa Sep 23 '14 at 02:32
  • 1
    What is confusing? The fact that `==` and `eql?` behave differently? If they behaved the same, then there would be no point for them both to exist. – sawa Sep 23 '14 at 02:36
  • There are so many result such as [this](http://stackoverflow.com/questions/7156955/whats-the-difference-between-equal-eql-and), and offical documents alse has [explanation](http://ruby-doc.org/core-2.1.3/Object.html#method-i-3C-3D-3E) – dddd1919 Sep 23 '14 at 02:50
  • Somehow it hadn't mattered until I came across finding the index in an array.[1,2.0,3].index(2) returns 1, which seemed wrong. This threw me off and I started to question fundamentals. – aarti Sep 23 '14 at 03:19
  • Related (not duplicate) Q&A: http://stackoverflow.com/q/25986896/1301972 – Todd A. Jacobs Sep 23 '14 at 07:37
  • There is so much interest in the question and the answer and comments have depth. I learnt a lot and the downvote is worth it!! – aarti Sep 23 '14 at 14:28

2 Answers2

4

because ruby tries to do a type-conversion with == but not with eql?

... and like @sawa said - it'd be inconvenient if that were not an option available to us. Comparing 0.0 with 0 for instance is really useful, and most of the time, whether an object is an int or a decimal doesn't really matter. (is 30 minutes the same as 30.0 minutes? do we care that one has .0 on the end?)

Patrick Oscity
  • 53,604
  • 17
  • 144
  • 168
Taryn East
  • 27,486
  • 9
  • 86
  • 108
  • 1
    I noticed that `2==3` invokes `Fixnum#==` whereas both `2.0==3.0` and `2==3.0` invoke `Comparable#==`. I'm especially curious why `Float#==` wasn't used in the first case. – Cary Swoveland Sep 23 '14 at 03:25
  • 1
    because 2 isn't a `Float`... it's an `Int`... therefore they can't use the standard `Float` comparison - which only works if they're both `Float`... otherwise they default to their super-classes `==` method, which presumably comes form the `Comparable` module. – Taryn East Sep 23 '14 at 04:24
  • 1
    When they're both Fixnums, then `Fixnum#==` is used, as expected. However, I redefined `Comparable#==` and found that it was being used for both `2.0==3.0` and `2==3.0`. It makes sense to me that Ruby would defer to `Comparable#==` when there are different numeric types, but I can't understand why `Float#==` wasn't used for `2.0==3.0`. – Cary Swoveland Sep 23 '14 at 04:39
  • 1
    @CarySwoveland `2.0 == 3.0` does call `Float#==` which in turn calls `Comparable#==` – Stefan Sep 23 '14 at 06:36
  • 1
    @Stefan, what then is the purpose of having `Float#==`? (I'm not questioning what you're saying--it must be true.) – Cary Swoveland Sep 23 '14 at 07:27
  • 1
    @CarySwoveland it was my fault: *my* `Float#==` implementation was calling `Comparable#==` because of `super` (and doing so returned wrong results). Ruby's `Float#==` implementation does not call `Comparable#==`. It handles everything itself, just like `Fixnum#==`. – Stefan Sep 23 '14 at 07:56
  • If everyone learned so much from the question, I did, then why the downvote, why not allow the asking of fundamental questions even if they are documented. – aarti Sep 23 '14 at 14:34
  • Hover your mouse over the down-vote button and you can see a list of things that people should down-vote for... it's not about whether the question is fundamental. – Taryn East Sep 23 '14 at 23:45
1

Numeric Type Conversions and Equality

Your question asks:

This is confusing. Why does this happen?

2.0 == 2   # => true  
2.0.eql? 2 # => false

This is documented behavior.

At the Object level, == returns true only if obj and other are the same object. Typically, this method is overridden in descendant classes to provide class-specific meaning...Numeric types, for example, perform type conversion across ==, but not across eql?

The documentation even gives these examples to illustrate:

1 == 1.0     #=> true
1.eql? 1.0   #=> false

In contrast, Float#eql? says:

Returns true only if obj is a Float with the same value as float. Contrast this with Float#==, which performs type conversions.

Todd A. Jacobs
  • 81,402
  • 15
  • 141
  • 199