[swift-evolution] Make distinction between ?? -> T and ?? -> T?
Pyry Jahkola
pyry.jahkola at iki.fi
Mon Mar 7 18:47:57 CST 2016
> On 07 Mar 2016, at 23:29, Sébastien Blondiau via swift-evolution <swift-evolution at swift.org> wrote:
>
> I think there should be two distinct operators:
>
> var certainlyOptional = value ?? otherValue
> var certainlyNotOptional = value ?! notOptionalValue
Consider a parallel Swiftverse where the standard library only defined the following single overload of `??`:
infix operator ?? { associativity right precedence 131 }
func ?? <T>(x: T?, @autoclosure y: () -> T) -> T {
if let x = x { return x } else { return y() }
}
With that defined, life went on and things worked just fine:
let some: Int? = 1
let none: Int? = nil
let one = some ?? 2 // = 1: Int
let two = none ?? 2 // = 2: Int
let ein = none ?? some ?? 3 // = 1: Int
(That last line, by the way, is equivalent to `none ?? (some ?? 3)` because of the right associativity.)
However, because of implicit optional wrapping, the following lines compiled as well:
let un = some ?? none // = Optional(1): Int?
let deux = 2 ?? none // = Optional(2): Int?
let rien = none ?? some // = nil: Int?
The reason was the compiler would Optional-wrap the left-hand side of `??` over and over again, until the argument pair met the shape `(T?, T)` for a type `T`, which happened to be `Int?` in this case:
some ?? none → Optional(some) ?? none
2 ?? none → Optional(Optional(2)) ?? none
none ?? some → Optional(none) ?? some
Don't you think the last line was especially surprising? Just a couple of lines up, the definition of `ein` looked almost identical:
let ein = none ?? some ?? 3 // = 1: Int
let rien = none ?? some // = nil: Int?
…yet with an entirely different result! Of course that's just because of associativity rules, but who remembered! So I guess in our world, the intention with the second overload `(T?, T?) -> T?` is beginner friendliness, and I can't argue against.
— Pyry
Epilogue: The parallel Swiftverse, however, went their own way and protected fellow swiftizens against indecision with:
enum Nope {}
@available(*, deprecated,
message="Your unwrappingness gets nowhere less Optional. See?")
func ** <T>(x: T?, y: T?) -> Nope { fatalError("How embarrassing!") }
Who knows, maybe one day they went on and invented a way to turn that thing into a compiler error? Who knows.
The End.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160308/e3e1b9bc/attachment.html>
More information about the swift-evolution
mailing list