The "spaceship" operator, <=>
doesn't return something so English as "a comes before b". It returns what sort
needs to know: where two elements are in relation to each other. Specifically, it returns the -1, 0, or 1 value you mentioned.
In a <=> b
, if a
is less than b
(via whatever comparison method is used for the class of which a
is an instance), the return is -1. If they're equal, return is 0; and if a
is greater than b
, the return is 1.
When you do b <=> a
, the returned value is based on b
rather than a
, so if a is smaller, you'll get 1, whereas you got -1 when doing a <=> b
.
So while the English meaning is the same, the devil is in the details: that -1, 0, or 1 return value. That value tells Ruby precisely how two elements fit into a sorted array.
The magic with those three numbers is in the quicksort algorithm used by Ruby. It's out of scope to try and explain precisely how that algorithm works, but you can basically look at it as a simple comparison on many values. For each item in an array, <=>
is called with another item in the array in order to determine where the two items fall relative to each other. Once enough comparisons have been made, the positions of all those individual items is known and the sorting is done.
As a simple (and not really technically accurate, but close enough) example, consider the array [3, 2, 7, 1]
. You can grab a value to compare others to in order to start the sorting. We'll pick 3. Running a comparison of 3 with all other numbers gives us:
3 <=> 2 == 1
: 3 is greater than 2, so 2 must be to the left of 3. Our array might look like this now: [2, 3, 7, 1]
3 <=> 7 == -1
: 3 is less than 7, so 7 must be the the right of 3. Our array continues to look as it did before, as the 7 was already on the right.
3 <=> 1 == 1
: 3 is greater than 1, so the 1 must be on the left of 3. Our array looks like this now: [2, 1, 3, 7]
We know the 7 must be correct since it's the only element on the "greater than 3" side. So we just need to figure out the sort order for everything before the 3: 1 and 2. Running a similar comparison as above, we obviously swap the 1 and 2 to get [1, 2, 3, 7]
.
I hope this helps!