In Swift 3, this is a compile error, if I use >
or <
let a: Int?
guard a > 0 else {return}
guard a < 0 else {return}
It makes perfect sense for the equality operator to support optionals, because it's absolutely clear that for any integer valued variable i
:
nil == nil
nil != i
i != nil
i == i
if and only if their values are the sameOn the other hand, it's not clear how comparison to nil
should act:
Is i
less than nil
?
nil
s come out at the end, then I would want i
to be less than nil
.nil
s come out at the start, then I would want i
to be greater than nil
.Since either of these are equally valid, it wouldn't make sense for the standard library to favor one over the other. It's left to the programmer to implement whichever comparison makes sense for their use-case.
Here's a toy implementation that generates a comparison operator to suite either case:
func nilComparator<T: Comparable>(nilIsLess: Bool) -> (T?, T?) -> Bool {
return {
switch ($0, $1) {
case (nil, nil): return true
case (nil, _?): return nilIsLess
case (_?, nil): return !nilIsLess
case let (a?, b?): return a < b
}
}
}
let input = (0...10).enumerated().map {
$0.offset.isMultiple(of: 2) ? Optional($0.element) : nil
}
func concisePrint<T>(_ optionals: [T?]) -> String {
return "[" + optionals.map { $0.map{ "\($0)?" } ?? "nil" }.joined(separator: ", ") + "]"
}
print("Input:", concisePrint(input))
print("nil is less:", concisePrint(input.sorted(by: nilComparator(nilIsLess: true))))
print("nil is more:", concisePrint(input.sorted(by: nilComparator(nilIsLess: false))))
Output:
Input:
[0?, nil, 2?, nil, 4?, nil, 6?, nil, 8?, nil, 10?]
nil is less:
[nil, nil, nil, nil, nil, 0?, 2?, 4?, 6?, 8?, 10?]
nil is more:
[0?, 2?, 4?, 6?, 8?, 10?, nil, nil, nil, nil, nil]
This is because Int
and Int?
are 2 different things.
According to the documentation, Int
has overloads for <
and >
and some other operators, while Optional only has overloads for ==
and !=
, see the documentation on Optional, the section talking about Comparing Optional Values.
Optional equality works logically, comparison doesn't.
5 == 5 = true
5 == nil = false
5 == 6 = false
nil == nil = true
Those all make sense, but these don't:
6 > 5 = true
5 > 5 = false
5 > nil = ??
nil > 5 = ??
This type of comparison does not have a simple answer, nor will that answer be the same depending on the use case.