Any good reason for Ruby to have == AND eql? ? (similarly with to_a and to_ary)

一曲冷凌霜 提交于 2019-12-06 01:33:04

I don't know the reasoning for this particular choice in ruby, but I'll just point out that equality is a difficult concept.

Common Lisp, for example has eq, eql, equal, equalp, and for that matter =

It can be very useful to be able to tell the difference between two references to the same object, two different objects of the same type with the same value, two objects with the same value but of different types, etc. How many variations make sense depends on what makes sense in the language.

If I recall it correctly (I don't use ruby), rubys predicates are implementing three of these cases

== is equality of value

eql? is equality of value and type

equal? is true only for the same object

== checks if two values are equal, while eql? checks if they are equal AND of the same type.

irb(main):001:0> someint = 17
=> 17
irb(main):002:0> someint == 17
=> true
irb(main):003:0> someint.eql? 17
=> true
irb(main):004:0> someint.eql? 17.0
=> false
irb(main):005:0> someint == 17.0
=> true
irb(main):006:0>

as you can see above, eql? will also test if both values are the same type. In the case of comparing to 17.0, which equates to false, it is because someint was not a floating point value.

This mentions that to_a and to_ary (and to_s and to_str , and to_i and to_int) have different levels of strictness. For example,

17.to_s

makes sense,

17.to_str

doesn't.

It seems that there is no to_ary method for the Hash class (no to_a), but for the Array class, to_a and to_ary have different behavior :

to_a :

Returns self. If called on a subclass of Array, converts the receiver to an Array object.

to_ary :

Returns self.

The answers above more that answer about eql? but here is something on to_a and to_ary. In Ruby's duck-typing scheme, objects can be converted two ways--loosely and firmly. Loose conversion is like saying: Can foo represent itself as an array (to_a). This is what to_a, to_s, to_i and other single letter ones are for. So a String can represent itself as an array, so it implements to_a. Firm conversion says something very different: Is foo a string (to_ary). Note that this is not wheather the class of foo is String, but whether foo and strings are interchangeable--whether anywhere a string is expected a foo could be logically used. The example in my Ruby book is of a Roman numeral class. We can use a Roman numeral anywhere we could use a positive integer, so Roman can implement to_int. Classes that have an are interchangeable relationship need to implement firm conversion, while loose is for almost all classes. Make sure not to use firm conversion where loose is right--code built into the interpreter will severely misunderstand you and you'll end up with bugs comparable to C++'s reinterpet_cast<>. Not good.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!