[swift-evolution] Make distinction between ?? -> T and ?? -> T?
Sébastien Blondiau
sebastien.blondiau at me.com
Thu Mar 10 06:49:18 CST 2016
Here is my proposal:
Distinction between ?? -> T? and ?? -> T
<https://github.com/HyperSeb/nil-coalescing-operator/tree/master#introduction>Introduction
The current nil coalescing operator can return an optional or not, depending on the second parameter.
The prosposed solution is the use of two distinct operators: ?? and ?!.
<https://github.com/HyperSeb/nil-coalescing-operator/tree/master#motivation>Motivation
Currently, the only nil coalescing operator may return an optional value or not. This variability can leads to unclear line of code:
var result = value ?? otherValue
where result may be an optional, and cannot be determined without looking for the definition of otherValue.
A real situation where I found the unique operator confusing was something like that:
func someFunction() -> T {
var someValue: T
/* some code */
var value = someOptionalValue ?? someValue
/* some code */
return value
}
For some reasons, I had to consider a new case where someValue had to be an optional
func someFunction() -> T {
var someValue: T?
/* some code */
var value = someOptionalValue ?? someValue
/* some code */
return value // error: value of optional type 'T?' not unwrapped; did you mean to use '!'
}
In my situation, the error was not at the return line but rather at the declaration of value. value was non optional in the first code and implicitly became optional in the second code.
<https://github.com/HyperSeb/nil-coalescing-operator/tree/master#proposed-solution>Proposed solution
A new operator ?! , which take a non optional second parameter and return a non optional value. This new operator replaces the current ?? which return a non optional.
This ensures the programmer knows if whether the value is optional or not:
var value = someOptionalValue ?? someValue // value is optional, without depending on someValue optionality
var value = someOptionalValue ?! someValue // value is not optional
// but if someValue is optional then this produces an error
The nil coalescing chaining benefits the same clarity:
var optionalValue = someArray ?? someFallback ?? secondaryFallback ?? tertiaryFallback
var nonOptionalValue = someArray ?? someFallback ?? secondaryFallback ?! tertiaryFallback
<https://github.com/HyperSeb/nil-coalescing-operator/tree/master#detailed-design>Detailed design
Under this proposal, the ?! operator has a lower precedence than ?? to have the described form of chaining: the operator ?! returns a non optional after that ?? has returned an optional.
infix operator ?? { associativity right precedence 131 }
+infix operator ?! { precedence 130 }
The ?! operator is non associative to avoid bad usages, which would lose some interest of the new operator:
-var nonOptionalValue = someArray ?! someFallback ?! secondaryFallback ?! tertiaryFallback
+var nonOptionalValue = someArray ?? someFallback ?? secondaryFallback ?! tertiaryFallback
Only the function ?? which returns a non optional is replaced:
-public func ??<T>(optional: T?, @autoclosure defaultValue: () throws -> T) rethrows -> T
+public func ?!<T>(optional: T?, @autoclosure defaultValue: () throws -> T) rethrows -> T
The internal implementation do not need to change.
<https://github.com/HyperSeb/nil-coalescing-operator/tree/master#impact-on-existing-code>Impact on existing code
This proposal will impact every code using the nil coalesing operator to get a non optional value.
The migration can be done automatically by replacing all ?? which currently return non optional value.
<https://github.com/HyperSeb/nil-coalescing-operator/tree/master#alternatives-considered>Alternatives considered
There are currently no alternatives considered.
Thoughts?
--
Sébastien Blondiau
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160310/e44a992e/attachment.html>
More information about the swift-evolution
mailing list