Spaceship Operator

Xcode 8.0, Swift 3, OSX 10.11

The following is a good example of creating your own operators. In the two years since first writing this, I have not found an actual use for this, but it appears to be a common operator in Ruby, and has been implemented several times in Swift.

My example code originally came from http://vperi.com/2014/06/05/spaceship-operator-in-swift/.

operator infix <=> {}
 
@infix func <=> (left: T, right: T) -> Int {
if left > right { return -1 }
  if left < right { return  1 }
  return 0
}

(‘func isLessOrEqualOrGreater’ just wouldn’t work half as well. Also, please note that at the time I copied this code – which was working – without stumbling over if… if, which is not a good construction.)

This is a good example where obscure symbols make code easier to read; something else to keep in mind.

Personally, I would prefer to return an enum:

enum ComparisonResult {
case lessThan
case equal
case greaterThan
}

or maybe, as suggested here,

enum Spaceship
{
case ← // LeftIsGreaterThanRight
case → // LeftIsLessThanRight
case ↔ // LeftIsEqualToRight
}

That led to a surprise. I tried this in a playground, and was promptly innundated with errors

ScreenShot2017-01-01at22.26.17-2014-07-1-16-31.pngScreenShot2017-01-01at22.25.46-2014-07-1-16-31.png

It seems as if Xcode parses ➡️ as -> and tries to use it as an operator. Good to know.

I have, out of sheer stubbornness, settled for a set of emojis with similar aesthetic, but slightly inappropriate wordings: back, on!, soon.

ScreenShot2017-01-01at22.28.42-2014-07-1-16-31.png

In July 2014, the world was simple;

operator infix <=> {}

@infix func <=> (left: T, right: T) -> Int {
if left < right { return 1 }
else if left > right { return -1 }
else { return 0 }
}

Paste that code now, and it explodes in errors.

‘Convert to Current Swift Syntax’ gives you

operator infix <=> {}

@inff <=>(left: T, right: T) -> Int {
if left < right { return 1 }
else if left > right { return -1 }
else { return 0 }
}

which, spoiler, does not solve any of the problems.

The correct code is

infix operator <=>

(this needs to be declared at global level)

func <=> (left: T, right: T) -> Spaceship {

if left < right {
return .🔙
} else if left > right {
return .🔙
} else {
return .🔛
}
}

In production, I would not use emoji, but here they illuminated an interesting Xcode quirk, and I did actually find it easier to work out what I wanted to return than I did with Ints or Strings.