在Ruby(1.9.3)中,为什么nil响应比较运算符,`<=>`?

kdb*_*man 3 ruby null comparable

对我来说,与其他任何东西(甚至是另一个null类型)进行比较的null类型是未定义的操作.如果我错了,请纠正我.

根据这个假设,以下内容对我有意义:

nil.is_a? Comparable
 => false

nil.respond_to? :<=
 => false

nil.respond_to? :<
 => false

nil.respond_to? :>=
 => false

nil.respond_to? :>
 => false
Run Code Online (Sandbox Code Playgroud)

但是,nil 确实响应"宇宙飞船"比较运算符:

nil.respond_to? :<=>
 => true
Run Code Online (Sandbox Code Playgroud)

我无法想象比较nil甚至有意义的情况,更不用说实际了.为什么nil会有这种行为?

Chr*_*ald 6

nil在Ruby中是一个单例实例NilClass,它继承自Object.对象实现<=>,其行为定义为:

如果obj和其他是相同的对象或obj == other,则返回0,否则返回nil.0表示自我等于其他.1意味着自我比其他人大.无意味着无法比较这两个值.

(参见文档)

因此,nil <=> nil返回0(它们是等价的),但nil <=> anything_else返回nil,这意味着"无法比较".

在Ruby中,期望所有对象都响应<=>(包括nil),但对于无意义或未定义操作的对象,返回值nil可以在最适合的调用代码处理.对于像#sort这样的Enumerable操作,它引发了一个异常:

[1, nil].sort
# => ArgumentError: comparison of NilClass with 1 failed
Run Code Online (Sandbox Code Playgroud)

但它不一定; 你可以实现自己的排序,只是将不可移动的值移动到列表的开头:

[1, nil, 2, 3, nil].sort {|a, b| (a <=> b) || -1 }
# => [nil, nil, 1, 2, 3]
Run Code Online (Sandbox Code Playgroud)