Rewbie Newbie

Documenting my path on becoming a Rails Developer.

What the Heck Is a Spaceship Operator?

While reading The Well-Grounded Rubyist I came across the perhaps the coolest sounding term in the Ruby language – the spaceship operator, aka “<=>”. How it functions is quite simple, as shown in the code below:

1
2
3
4
5
6
7
2 <=> 3 #=> -1
2 <=> 2 #=> 0
2 <=> 1 #=> 1

"b" <=> "c" #=> -1
"b" <=> "b" #=> 0
"b" <=> "a" #=> 1

Basically the operator returns “1” if the object on left of the operator is greater than the object to the right, “-1” is returned if the left object is less than the right object, and “0” is returned if the left object is equal to the right object.

But, the duties of the spaceship operator does not just end with operating on strings and numbers, it has much deeper implications on the Ruby language. When you want to compare objects of the same class, you include the Comparable module in the class and then redefine the spaceship method. I will demonstrate the process in the following code sample:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Baller
  include Comparable

  attr_accessor :rank
  attr_reader :name

  def initialize(name)
    @name = name
  end

  def <=>(player)                   # 'player' is an arbitrary name for a variable.  
    if self.rank < player.rank      # It is necessary to name the object you are  
      1                             # comparing self with.
    elsif self.rank > player.rank
      -1
    else
      0
    end
  end

end

kb = Baller.new("Kobe Bryant")
kb.rank = 2

mj = Baller.new("Michael Jordan")
mj.rank = 1

lj = Baller.new("LeBron James")
lj.rank = 3

puts mj > kb #=> true
puts kb < lj #=> false

As you can see, even though mj has a rank of 1 and kb has a rank of 2 and numerically speaking 2 is greater than 1, the outcome does not reflect that. By redefining the spaceship method, I changed the meaning of “>” and “<” to evaluate to the exact opposite of what they traditionally do, they now evaluate to “greater than” and “less than” based on ordinal value rather than numerical value.

(And yes, I did put Kobe ahead of LeBron.)