在Ruby中,为什么与nil("Date.new == nil")的相等性返回nil?

Gab*_*esy 17 ruby equality date

今天写一些rspec时,我遇到了一些意外行为,将Date(和Time)实例与nil进行比较.这是使用原始ruby(没有Rails或其他库)的示例:

user@MacBook-Work ~ $ ruby -v
ruby 1.8.7 (2008-08-11 patchlevel 72) [universal-darwin10.0]
user@MacBook-Work ~ $ irb
>> 1 == nil
=> false
>> "string" == nil
=> false
>> :sym == nil
=> false
>> false == nil
=> false
>> [] == nil
=> false
>> {} == nil
=> false
>> Proc.new {} == nil
=> false
Run Code Online (Sandbox Code Playgroud)

到目前为止,这么好,对吗?

>> Date.new == nil
=> nil
>> Time.new == nil
=> nil
Run Code Online (Sandbox Code Playgroud)

Date确实实现了自己的===,这很好用:

>> Date.new === nil
=> false
Run Code Online (Sandbox Code Playgroud)

有没有解释为什么会发生这种情况或为什么这是理想的行为?==似乎是从Comparable实现的.==,但是关于它的文档没有任何迹象表明它会返回nil.对此有何设计决定?

更新!1.9.2中的情况并非如此:

$ irb
ruby-1.9.2-p136 :001 > require 'date'
 => true 
ruby-1.9.2-p136 :002 > Date.new == nil
 => false 
ruby-1.9.2-p136 :003 > Time.new == nil
 => false 
Run Code Online (Sandbox Code Playgroud)

sep*_*p2k 12

我检查了源代码,这是我发现的:

Comparable定义的比较运算符都与函数rb_cmpint一起使用<=>.rb_cmpint当其中一个操作数为零时引发异常.

因此,如果rhs与lhs不具有可比性,则Comparable的运算符会引发异常.即5 < 2是假的,但5 < "la"引发了一个例外.他们这样做是为了区分<因为rhs较小而不适用的情况以及由于rhs不具有可比性而不适用的情况.或者换句话说:什么时候x < y是假的,暗示这x >= y是真的.因此,如果不是这种情况,它会引发异常.

==提出异常会很糟糕,因为==通常不会(也不应该)要求其操作数具有可比性.但是==使用与其他操作数相同的方法,这会引发异常.所以整个功能简单地包裹在一个rb_rescue.nil如果抛出异常,则返回.

请注意,这仅适用于ruby 1.8.这已在1.9中修复,现在==永远不会返回nil(当然,如果您定义自己的==那个).


Pet*_*own 7

如果您依赖于此代码,您可以随时使用.nil?任何Ruby对象响应的方法.

>> Date.new.nil?
=> false
Run Code Online (Sandbox Code Playgroud)