Why can't Swift more or less than operators compare options when equality operators can?
In Swift 3, it is a compilation error if I use >
or<
let a: Int?
guard a > 0 else {return}
guard a < 0 else {return}
Compilation error:
Value of the optional type 'Int?' does not unfold; you wanted to use '!' or '?'?
But it's ok if I compare with ==
or!=
let a: Int?
guard a == 0 else {return}
guard a != 0 else {return}
source to share
It makes sense for the equality operator to support helper members, since it's absolutely clear that for any integer variable i
:
-
nil == nil
-
nil != i
-
i != nil
-
i == i
if and only if their values are the same
On the other hand, it is not clear how the comparison with nil
:
Is it i
less nil
?
- If I want to sort the array so that everything
nil
comes out at the end, then I would like it toi
be smallernil
. - But if I want to sort the array so that everything
nil
comes out at the beginning, then I would like it toi
be greater thannil
.
Since either of them is equally true, it makes no sense for the standard library to support one over the other. It was left to the programmer to realize that the comparison makes sense for their use.
Here's a toy that generates a comparison operator in any of them:
func nilComparitor<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 % 2 == 0 ? Optional($0.element) : nil
}
print("Input:", input)
print("\r\n\r\n\r\n")
print("nil is less: ", input.sorted(by: nilComparitor(nilIsLess: true)))
print("\r\n\r\n\r\n")
print("nil is more: ", input.sorted(by: nilComparitor(nilIsLess: false)))
Output:
Input: [Optional (0), zero, optional (2), zero, optional (4), zero, Optional (6), nil, Optional (8), nil, Optional (10)]
nil is less than: [nil, nil, nil, nil, nil, optional (0), optional (2), Optional (4), Optional (6), Optional (8), Optional (10)]
nil is greater than: [Optional (0), Optional (2), Optional (4), Optional (6), Optional (8), Optional (10), nil, nil, nil, nil, nil]
source to share
This is because Int
and Int?
are two different things.
According to the documentation , it Int
has overloads for <
and >
and some other operators, while optionally only has overloads for ==
and !=
, see the documentation in the Advanced section , in the section on comparing optional values.
source to share
Complementary equality works logically, but comparison does not.
- 5 == 5 = true
- 5 == nil = false
- 5 == 6 = false
- nil == nil = true
This all makes sense, but it doesn't:
- 6> 5 = true
- 5> 5 = false
- 5> nil = ??
- nil> 5 = ??
This type of comparison has no simple answer, and this answer will not be the same depending on the use case.
source to share