This week on Ruby Bits we've decided to honour the Juno mission entering
Jupiter's orbit by discuss
another special operator in Ruby, commonly known as the spaceship operator
(because it looks like one). You've probably come across it at some point, but
if not, here's what I'm talking about:
RubyConf Portugal 2016 discount code
Perl was likely the first language to introduce this operator as it is seen in Ruby, but the same concept exists in Java or C# as part of their Comparable interfaces.
How it works in Ruby
The spaceship operator in Ruby has four possible return values,
nil. It will return
nil only if the two objects are not comparable. If
they are comparable, it will return
-1 if the caller object is considered less
than the argument (whatever that means for these objects), it returns
they are equal and
Sounds confusing? Let's look at an example that will make it clearer:
1 <=> 4 #=> -1 4 <=> 4 #=> 0 8 <=> 4 #=> 1 7 <=> "hello" #=> nil
Where to use it?
If you've never used this operator directly, you might be wondering why would
you care about it, or where should you use it. It turns out that
<=> is the
foundation to everything in the
module. When it is implemented for a class, it allows you to use the more common
comparison methods such as
between? or even
As you can probably guess, Ruby already implements this for the core classes,
Object which means your custom classes will also have a very basic
(and usually not very useful) version of the spaceship operator.
Making my class comparable
As I've stated above, all objects can be compared with objects of the same class
by default, that comparison might not be exactly what you want though. Let's
create a brand new
Dummy class and see how it behaves:
class Dummy end d1 = Dummy.new d2 = Dummy.new d1 <=> d2 #=> nil d1 < d2 #=> undefined method `<'
Woah! What just happened? Well, when the spaceship operator returns
Comparable methods work, and the
Object's version of
nil for every case, expect when the objects being compared are the exactly the same.
d1 <=> d1 would return
In order to make
Dummy actually comparable we need to really implement the
spaceship operator, like so:
class Dummy include Comparable def <=>(other) 0 end end d1 = Dummy.new d2 = Dummy.new d1 <=> d2 #=> 0 d1 < d2 #=> false
Notice that we included the
Comparable module and then implemented the
method to always return
0, which means all instances of this class are
considered equal. So that we can write a more interesting method, let's also add
a string attribute that we can compare:
class Dummy include Comparable attr_reader :name def initialize(name) @name = name end def <=>(other) name <=> other.name end end d1 = Dummy.new("hello") d2 = Dummy.new("world") d1 <=> d2 #=> -1 d1 < d2 #=> true
In this example we are simply delegating
String, which in turn will declare that
"hello" is less than
"world" because the unicode code point for
h is 104 and the one for
w is 119 and that's what's actually being compared.
More Ruby Bits
If you've enjoyed this Ruby Bit you should really subscribe to our newsletter, where other Ruby Bits and more great articles are shared every week.