【问题标题】:Any good reason for Ruby to have == AND eql? ? (similarly with to_a and to_ary)Ruby 有 == AND eql 有什么好的理由吗? ? (与 to_a 和 to_ary 类似)
【发布时间】:2009-04-20 22:55:25
【问题描述】:

我知道 eql 吗? Hashes 使用它来查看一个对象是否与 key* 匹配,而你这样做

def ==(rb)

如果您想支持 == 运算符,但必须有充分的理由让哈希不使用 == 代替。这是为什么?你什么时候有 == 和 eql 的定义? 等效(例如,一个是另一个的别名)?

同理,为什么除了to_a还要to_ary?

这个问题是为了回应某人在another question 上给我的answer

*当然,一个Hash也假设eql? == true 表示哈希码相等。

另外,重写 equal 基本上是一个可怕的想法吗? ?

【问题讨论】:

标签: ruby methods


【解决方案1】:

== 检查两个值是否相等,而 eql?检查它们是否相等且属于同一类型。

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>

正如你在上面看到的,eql?还将测试两个值是否为同一类型。与 17.0 相比,等于 false,这是因为 someint 不是浮点值。

【讨论】:

    【解决方案2】:

    我不知道在 ruby​​ 中做出这种特殊选择的原因,但我只想指出,平等是一个困难的概念。

    Common Lisp,例如有 eq、eql、equal、equalp,就此而言 =

    能够区分对同一个对象的两个引用、具有相同值的相同类型的两个不同对象、具有相同值但不同类型的两个对象等之间的区别是非常有用的。变化是否有意义取决于语言中什么是有意义的。

    如果我没记错的话(我没有使用 ruby​​),rubys 谓词正在实现其中三种情况

    == 是相等的值

    eq?是值和类型相等

    相等?仅适用于同一个对象

    【讨论】:

    • 我可以告诉你实际上考虑过这个答案。在迄今为止发布的那些中,这一篇最直接地回答了“为什么要区分”这个问题,这正是我一直在寻找的。其他人更倾向于“有什么区别”。我也喜欢您指出这是一个通用语言设计问题的方式。确实,在平等方面,有很多事情要做!
    【解决方案3】:

    This 提到 to_a 和 to_ary(以及 to_s 和 to_str 以及 to_i 和 to_int)具有不同级别的严格性。例如,

    17.to_s
    

    有道理,

    17.to_str
    

    没有。

    【讨论】:

    • 感谢您的链接。这解释了一些原因,尽管我仍然不相信。另外,我认为你的意思是“对 Ruby 来说有意义”。对我来说,17.to_s 有效但 17.to_str 无效,这毫无意义。
    • to_s/to_a/to_f/to_i 都是显式转换。 to_str/to_ary/to_int 都是隐式转换。例如,我有一个自己编写的 URI 库。我的 URI 类实现了 to_str,因为如果我有一个将字符串形式的 URI 作为参数的方法,我不想在将其作为参数传递之前将我的 URI 对象显式转换为字符串。 to_str 方法允许我这样做。
    【解决方案4】:

    Hash 类似乎没有 to_ary 方法(没有 to_a),但是对于 Array 类,to_a 和 to_ary 的行为不同:

    到_a:

    返回自我。如果在 Array 的子类上调用,则将接收器转换为 Array 对象。

    to_ary:

    返回自我。

    【讨论】:

      【解决方案5】:

      上面的答案更多的是关于eql? 的答案,但这里有一些关于to_ato_ary 的内容。 在 Ruby 的鸭子类型方案中,对象可以通过两种方式进行转换——松散和牢固。松散转换就像说: foo 可以将自己表示为一个数组 (to_a)。这就是to_ato_sto_i 和其他单字母的用途。所以一个String可以将自己表示为一个数组,所以它实现了to_a。坚定的转换说的是非常不同的东西:foo 是一个字符串 (to_ary)。请注意,这不是 foo 的类是否为 String,而是 foo 和 strings 是否可互换——无论在任何需要字符串的地方,是否都可以在逻辑上使用 foo。我的 Ruby 书中的示例是罗马数字类。我们可以在任何可以使用正整数的地方使用罗马数字,所以 Roman 可以实现to_int。 具有可互换关系的类需要实现牢固转换,而松散则几乎适用于所有类。确保不要在松散正确的地方使用严格的转换——解释器中内置的代码会严重误解你,你最终会遇到类似于 C++ 的reinterpet_cast<> 的错误。不好。

      【讨论】:

        猜你喜欢
        • 2012-06-26
        • 2013-08-12
        • 1970-01-01
        • 2012-02-16
        • 1970-01-01
        • 1970-01-01
        • 2011-03-14
        相关资源
        最近更新 更多