[swift-evolution] Make distinction between ?? -> T and ?? -> T?

Thorsten Seitz tseitz42 at icloud.com
Thu Mar 10 11:59:06 CST 2016


I agree with Shawn an Jordan.
-1 to the proposal.

-Thorsten 

> Am 10.03.2016 um 18:29 schrieb Shawn Erickson via swift-evolution <swift-evolution at swift.org>:
> 
> -1 on ?! since it doesn't trap like others uses of !
> -1 on the need for this, the compiler won't let you do the wrong thing here, yeah I understand that at a glance a human can't quickly tell however the same thing happens things that return an option when assigned into a var/let
> 
>> On Thu, Mar 10, 2016 at 9:23 AM Jordan Rose via swift-evolution <swift-evolution at swift.org> wrote:
>> I forgot to mention it but I'm (also?) very much against adding a new operator with "!" in the name that won't ever trap. The "not" operator got pulled in from C, but every other use of "!" means "I am asserting I know more than the compiler does" (or perhaps more accurately "there is a precondition here that the compiler doesn't know about"). That includes !-to-unwrap, ImplicitlyUnwrappedOptional, 'as!', and 'try!'.
>> 
>> Jordan
>> 
>> 
>>> On Mar 10, 2016, at 4:49 , Sébastien Blondiau via swift-evolution <swift-evolution at swift.org> wrote:
>>> 
>>> Here is my proposal:
>>> 
>>> Distinction between ?? -> T? and ?? -> T
>>> 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 ?!.
>>> 
>>> 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.
>>> 
>>> 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
>>> 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.
>>> 
>>> 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.
>>> 
>>> Alternatives considered
>>> 
>>> There are currently no alternatives considered.
>>> 
>>> Thoughts?
>>> 
>>> --
>>> Sébastien Blondiau
>>> 
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution at swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160310/54aeed58/attachment.html>


More information about the swift-evolution mailing list