NilClass and Comparable


#1

nil==0
=> false

class NilClass
include Comparable
def <=>(other)
0
end
end
=> nil

[1,nil,2].sort
ArgumentError: comparison of Fixnum with nil failed
from (irb):11:in `sort’
from (irb):11

p nil > 2
false
=> nil

p nil > -1
false
=> nil

p nil == 0
true
=> nil

What I am missing here?


#2

removed_email_address@domain.invalid wrote:

nil==0
=> false

class NilClass
include Comparable
def <=>(other)
0
end
end
=> nil

[1,nil,2].sort
ArgumentError: comparison of Fixnum with nil failed
from (irb):11:in `sort’
from (irb):11

p nil > 2
false
=> nil

p nil > -1
false
=> nil

p nil == 0
true
=> nil

What I am missing here?

Probably this:

irb(main):003:0> class NilClass
irb(main):004:1> def <=>(other)
irb(main):005:2> 0
irb(main):006:2> end
irb(main):007:1> end
=> nil
irb(main):008:0> nil <=> 1
=> 0
irb(main):009:0> 1 <=> nil
=> nil
irb(main):010:0>


#3

Yes! Thats exactly what I was missing. Why would someone write <=> for
nil?


#4

Robert K. wrote:

On 09.05.2009 01:35, removed_email_address@domain.invalid wrote:

Yes! Thats exactly what I was missing. Why would someone write <=> for nil?

There is probably no good reason because nothing doesn’t compare well to
anything - and so the method is not defined. :slight_smile:

It can be useful to have an ordering defined for mixed collections. For
example, CouchDB defines a full ordering across null, numbers, strings,
arrays and objects (hashes):
http://wiki.apache.org/couchdb/View_collation

In Ruby, the solution depends on what exactly you’re trying to do. Maybe
sort_by with a default value is good enough for what you need.

arr.sort_by { |e| e || -1 }

You can also use arr.sort { |a,b| … } and then the block defines the
‘<=>’ logic for comparing two objects.

Note that it would be dangerous to define nil <=> any and any <=> nil to
be 0, because that would mean (any number) == nil == (any other number).
For example,

[2, nil, 1]

could be treated as an already-sorted array!

Instead, you might want to define nil <=> x as -1 and x <=> nil as +1
(where x is any non-nil value). You can do that in your sort block.

Regards,

Brian.

P.S. Also be aware that ruby’s sort is implemented using quicksort
(IIRC), which is not stable for equal keys.


#5

On 09.05.2009 01:35, removed_email_address@domain.invalid wrote:

Yes! Thats exactly what I was missing. Why would someone write <=> for nil?

There is probably no good reason because nothing doesn’t compare well to
anything - and so the method is not defined. :slight_smile:

Kind regards

robert