Comparison of Float::NAN in array behaves unexpectedly
It seems that two arrays containing Float::NAN will be considered equal ([Float::NAN] == [Float::NAN]), despite the fact that Float::NAN != Float::NAN.
Tested and reproduced in 1.8.7p371, 1.9.3p362, 2.0.0preview2. (This bug can be reproduced in Ruby 1.8 as well.) Results below.
1.8.7 :001 > nan = 0.0/0.0
1.8.7 :002 > nan == nan
1.8.7 :003 > [nan] == [nan]
1.9.3p362 :001 > Float::NAN == Float::NAN
1.9.3p362 :002 > [Float::NAN] == [Float::NAN]
2.0.0dev :001 > Float::NAN == Float::NAN
2.0.0dev :002 > [Float::NAN] == [Float::NAN]
#1 [ruby-core:51334] Updated by charliesome (Charlie Somerville) over 5 years ago
Attached a patch fixing this issue - the pointer equality checks in
rb_equal should not be performed as this breaks in the case where
a != a.
I'm not committing this straight away because it causes three test failures due to brittle mocks.
#3 [ruby-core:51336] Updated by simonrussell (Simon Russell) over 5 years ago
This isn't just
Float::NAN, actually; as Charlie's patch shows, it's actually any object that always returns false from
1.9.3p125 :001 > class X 1.9.3p125 :002?> def ==(other) 1.9.3p125 :003?> false 1.9.3p125 :004?> end 1.9.3p125 :005?> end => nil 1.9.3p125 :006 > x = X.new => #<X:0x00000000ba1648> 1.9.3p125 :007 > x == x => false 1.9.3p125 :008 > [x] == [x] => true
Is this desirable behaviour?
#5 [ruby-core:51339] Updated by hasari (Hiro Asari) over 5 years ago
I, too, found documentation still lacking. I read #1720, and I understand the rationale for the Float::NAN case.
However, the issue still remains as Simon pointed out above. Please reopen the issue, or update the documentation to reflect the behavior more closely.
#10 [ruby-core:72887] Updated by dwfait (Dwain Faithfull) over 2 years ago
It appears calling eql? on array does not behave in this way:
[Float::NAN].eql? [Float::NAN] => false
Should we aim for consistency between these methods? Does it make sense for one to have an identity check and for the other not to?
I believe it doesn't really make sense for == to have an identity check, as the example in #3 is not how I'd expect Ruby to behave.