[swift-evolution] ? suffix for <, >, <=, >= comparisons with optionals to prevent subtle bugs

thorsten at portableinnovations.de thorsten at portableinnovations.de
Thu Dec 10 11:30:30 CST 2015

>> let ps = peeps.filter { $0.pet?.age.map { age in age < 6 } ?? false }

> It’s curious that your example won’t compile (didn’t when I tried it in a Playground)

You are right, the example does not compile (wrote it in the train far away from Xcode). It gives an error of „value of type ‚Int‘ has no member ‚map‘“.

Hmm, I consider that as a bug in the definition of optional chaining, as the documentation clearly states 
"Optional chaining is a process for querying and calling properties, methods, and subscripts on an optional that might currently be nil. If the optional contains a value, the property, method, or subscript call succeeds; if the optional is nil, the property, method, or subscript call returns nil.“ (note the last sentence).

So if $0.pet?.age should return nil in case of $0.pet being nil, the type of $0.pet?.age has to be Int? and therefore understand map().

peeps[0].pet?.age.dynamicType      // => Int.Type this is wrong!! Should be Optional<Int>.Type
let y: Int = peeps[1].pet?.age     // This gives a type error which is right (but inconsistent with the dynamicType just claimed)
let x = peeps[1].pet?.age          // Now let’s see what the type is after assigning the expression
x.dynamicType                      // => Optional<Int>.Type as expected
x.map { age in age < 6 } ?? false  // => false as expected

So, obviously a bug in the compiler.

> My perspective is still that the issue isn’t with Optionals being comparable, but in certain edge cases the auto wrapping of non Optionals is what causes the confusion, as it’s not obvious that the comparison is between Optionals.

You are certainly right that the real issue is with auto wrapping.

> Regarding the default semantics, I’d say the semantics of Optional comparison is pretty reasonable and fits with:
> "" < "abc" == true
> [] < [1,2,3] == true
> .None < .Some(0) == true

You have me convinced here as the cases for the String and the List are quite convincing and the analogy with .None and .Some compelling.

Just checked: Haskell defines the same order for its Maybe monad, i.e. (Nothing < Just 0) == True.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151210/adc72a36/attachment.html>

More information about the swift-evolution mailing list