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

北慕城南 提交于 2019-12-07 15:39:36

问题


I know eql? is used by Hashes to see if an object matches a key*, and you do

def ==(rb)

if you want to support the == operator, but there must be a good reason that Hashes don't use == instead. Why is that? When are you going to have definitions for == and eql? that are not equivalent (e.g. one is an alias to the other) ?

Similarly, why have to_ary in addition to to_a?

This question came up in response to an answer someone gave me on another question.

* Of course, a Hash also assumes eql? == true implies that the hashes codes are equal.

Also, is it basically a terribly idea to override equal? ?


回答1:


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




回答2:


== 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.




回答3:


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.




回答4:


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.




回答5:


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.



来源:https://stackoverflow.com/questions/770418/any-good-reason-for-ruby-to-have-and-eql-similarly-with-to-a-and-to-ary

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