I’ve taken time to digest all the messages on this discussion and would like to
summarise my point of view concerning several topics:
Usefulness of messages
Xiaodi seems to question the usefulness of attaching more information to the
failure case of an optional's unwrapping. To his credit, the original example
("Array guaranteed non-empty") don’t add much. Instead, I think we should see
those strings as a great opportunity to add application-specific business logic
context that help debugging when the unwrapping fails. For example, let’s
imagine that I am handling the log out operation for a user I know exists, I
could write this:
let user = database.users[userId] !! “User to logout does not exist”
Never and new operator
If we introduce the new operator !! solely with the String override, I still
have some doubts about it pulling its own weight. Of course, we could add a ()
-> Never override to increase its usefulness:
let user = database.users[userId] !! “User to logout does not exist”
let user = database.users[userId] !! logFatalError(“User to logout does not
exist”)
But Jaden Geller makes a very good point: if and once Never becomes a true
bottom type, that syntax will be redundant because Never will be usable with
the ?? operator, creating a lot of confusion:
let user = database.users[userId] !! logFatalError(“User to logout does not
exist”)
let user = database.users[userId] ?? logFatalError(“User to logout does not
exist”)
Those two lines will have exactly the same effect.
Cognitive Dissonance of Never and ??
Ben Cohen originally mentioned that if we introduce a () -> Never overload of
the ?? operator, there will be cognitive dissonance because the question mark
operator is never used in Swift to signal a trap. But if we make Never a true
bottom type, which has a lot of advantages, this dissonance will be
unavoidable. Shouldn’t we embrace it then?
Potential for confusion with multiple per line
This might not be a real concern, but are we introducing a syntax that will
make it possible/encourage people to write less than readable code?
let user = (database !! “Database is not operational”).users[userId !! “User
was not set in time”] !! “User to logout does not exist"
David.
> On 28 Jun 2017, at 22:30, Erica Sadun via swift-evolution
> <[email protected]> wrote:
>
> Based on the feedback on this thread, I'm coming to the following conclusions:
>
> `!!` sends the right semantic message. "Unwrap or die" is an unsafe
> operation. It is based on `!`, the unsafe forced unwrap operator, and not on
> `??`, the safe fallback nil-coalescing operator. Its symbology should
> therefore follow `!` and not `?`.
>
> The `!!` operator should follow the same semantics as
> `Optional.unsafelyUnwrapped`, which establishes a precedent for this approach:
>
> > "The unsafelyUnwrapped property provides the same value as the forced
> > unwrap operator (postfix !). However, in optimized builds (-O), no check is
> > performed to ensure that the current instance actually has a value.
> > Accessing this property in the case of a nil value is a serious programming
> > error and could lead to undefined behavior or a runtime error."
>
> By following `Optional.unsafelyUnwrapped`, this approach is consistent with
> https://github.com/apple/swift/blob/master/docs/ErrorHandlingRationale.rst#logic-failures
>
> <https://github.com/apple/swift/blob/master/docs/ErrorHandlingRationale.rst#logic-failures>
>
> > "Logic failures are intended to be handled by fixing the code. It means
> > checks of logic failures can be removed if the code is tested enough.
> Actually checks of logic failures for various operations, `!`, `array[i]`,
> `&+` and so on, are designed and implemented to be removed
> when we use `-Ounchecked`. It is useful for heavy computation like image
> processing and machine learning in which overhead of those checks is not
> permissible."
>
> The right hand side should use a string (or more properly a string
> autoclosure) in preference to using a `Never` bottom type or a `() -> Never`
> closure. A string provides the cleanest user experience, and allows the
> greatest degree of self-documentation.
>
> - A string is cleaner and more readable to type. It respects DRY, and avoids
> using *both* the operator and the call to `fatalError` or
> `preconditionFailure` to signal an unsafe condition:
> `let last = array.last !! “Array guaranteed non-empty" // readable`
> than:
> `let last = array.last !! fatalError(“Array guaranteed non-empty”) //
> redundant, violates DRY`
>
> - A string allows the operator *itself* to unsafely fail, just as the unary
> version of `!` does now. It does this with additional feedback to the
> developer during testing, code reading, and code maintenance. The string
> provides a self-auditing in-line annotation of the reason why the forced
> unwrap has been well considered, using a language construct to support this.
>
> - A string disallows a potentially unsafe `Never` call that does not reflect
> a serious programming error, for example:
> let last = array.last !! f() // where func f() -> Never { while true {} }
>
> - Although as several list members mention, a `Never` closure solution is
> available today in Swift, so is the `!!` operator solution. Neither one
> requires a fundamental change to the language.
>
> - Pushing forward on this proposal does not in any way reflect on adopting
> the still-desirable `Never` bottom type.
>
>> On Jun 28, 2017, at 12:42 PM, Tony Allevato via swift-evolution
>> <[email protected] <mailto:[email protected]>> wrote:
>>
>>
>>
>> On Wed, Jun 28, 2017 at 11:15 AM Dave DeLong <[email protected]
>> <mailto:[email protected]>> wrote:
>>> On Jun 28, 2017, at 10:44 AM, Adrian Zubarev via swift-evolution
>>> <[email protected] <mailto:[email protected]>> wrote:
>>>
>>> Well the main debate is that, we all want early access to a feature that
>>> will be part of Swift as soon as `Never` becomes the bottom type. When this
>>> happens the `??` will automatically support the pitched behavior. Until
>>> then if we all agree that we should add it now in a way that will not break
>>> anything we can simply add an overload to `??` as I previously showed.
>>>
>>
>> I believe we should add it now, but I like the recent observation that
>> making ?? suddenly become a potentially crashing operator violates the
>> expectation that ? is an indication of safety.
>>
>> ?? does *not* become a potentially crashing operator. The *fatalError* (or
>> whatever else the user chooses to put there) on the right-hand side is the
>> crashing operation.
>>
>>
>> On the other hand, the existing semantics of Swift are that ! is always
>> dangerous, so making !! be the a potentially crashing operator is much more
>> consistent with the language.
>>
>>> There is no need for `!!` because it will fade in the future. If you think
>>> of `Never` as a bottom type now then `??` will already make total sense.
>>> The default value for T from rhs might be T or Never.
>>
>> I respectfully disagree with your absolute position on this topic. Even with
>> Never as a bottom type in the future, it would still be more convenient for
>> me to type:
>>
>> let last = array.last !! “Array must be non-empty"
>>
>> … than it ever would be to type:
>>
>> let last = array.last ?? fatalError(“Array must be non-empty”)
>>
>>
>> There is a very high bar for additions to the standard library—a new
>> operator added to the language is going to be around (1) forever, or (2)
>> indefinitely with some migration cost to users if it's ever removed. Shaving
>> off a few keystrokes doesn't quite meet that bar—especially when an
>> alternative has been shown to work already that provides the same
>> functionality, is more general (not coupled to fatalError or String
>> messages), and that fits better into Swift's design.
>>
>>
>> To make sure I'm not being too much of a downer, I would completely support
>> this broader feature being implemented by that alternative: the ?? +
>> autoclosure () -> Never combo. Then once Never does become a true bottom
>> type, I believe it could be removed and the calling code would still *just
>> work*.
>>
>>
>> Dave
>>
>>>
>>> @erica: the rhs argument should be called something like `noreturnOrError`
>>> and not `defaultValue`. And we should keep in mind that when Never becomes
>>> the bottom type we have to remove that overload from stdlib, because
>>> otherwise it will be ambiguous.
>>>
>>> ---
>>>
>>> On the other hand if we tackle a different operator then we should rething
>>> the 'default value operator' because the second ? signals an optional but
>>> not a non-optional or an inplicit unwrapped operator. In that case I
>>> personally thing ?! would make more sense. Unwrap or (non-optional | IUO |
>>> trap/die)
>>>
>>> --
>>> Adrian Zubarev
>>> Sent with Airmail
>>> Am 28. Juni 2017 um 18:13:18, Tony Allevato via swift-evolution
>>> ([email protected] <mailto:[email protected]>) schrieb:
>>>
>>>> It's hard for me to articulate, but "foo !! message" feels a little too
>>>> much like a Perl-ism for my taste. Objectively that's not a great
>>>> criticism on its own, but I just don't like the "smell" of an operator
>>>> that takes a value on one side and a string for error reporting purposes
>>>> on the other. It doesn't feel like it fits the style of Swift. I prefer a
>>>> version that makes the call to fatalError (and thus, any other
>>>> non-returning handler) explicitly written out in code.
>>>>
>>>> So, if the language can already support this with ?? and autoclosure/Never
>>>> as was shown above, I'd rather see that added to the language instead of a
>>>> new operator that does the same thing (and is actually less general).
>>>>
>>>> On Wed, Jun 28, 2017 at 8:52 AM Jacob Williams via swift-evolution
>>>> <[email protected] <mailto:[email protected]>> wrote:
>>>> I feel that the !! operator would be necessary for indicating that if this
>>>> fails then something went horribly wrong somewhere and we should throw the
>>>> fatalError. This allows the inclusion of optimizations using -Ounchecked
>>>> and is clear that this is an operation that could result in a runtime
>>>> error just like force unwrapping.
>>>>
>>>> If we want code clarity and uniformity, then I think !! Is much better
>>>> than ?? because it goes right along with the single ! Used for force
>>>> unwrapping. However, this does depend on if the operator would be
>>>> returning some kind of error that would cause the program to exit.
>>>>
>>>> I think the ?? operator should not cause a program to exit early. It goes
>>>> against optional unwrapping principles. I think code could get very
>>>> confusing if some ? would return nil/a default value, and others would be
>>>> causing your program to crash and exit. The ? operators should always be
>>>> classified as safe operations.
>>>>
>>>>> On Jun 28, 2017, at 9:41 AM, Ben Cohen via swift-evolution
>>>>> <[email protected] <mailto:[email protected]>> wrote:
>>>>>
>>>>>
>>>>>> On Jun 28, 2017, at 8:27 AM, David Hart via swift-evolution
>>>>>> <[email protected] <mailto:[email protected]>> wrote:
>>>>>>
>>>>>> Count me in as a strong proponent of ?? () -> Never. We don't need to
>>>>>> burden the language with an extra operator just for that.
>>>>>
>>>>> You could say the same about ??
>>>>>
>>>>> The concern that an additional operator (and one that, IMO, fits well
>>>>> into existing patterns) is so burdensome seems way overweighted in this
>>>>> discussion IMO.
>>>>>
>>>>> Adding the operator, and encouraging its use, will help foster better
>>>>> understanding of optionals and legitimate use of force-unwrapping in a
>>>>> way that I don’t think `?? fatalError` could.
>>>>>
>>>>>
>>>>> _______________________________________________
>>>>> swift-evolution mailing list
>>>>> [email protected] <mailto:[email protected]>
>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>>
>>>> _______________________________________________
>>>> swift-evolution mailing list
>>>> [email protected] <mailto:[email protected]>
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>> _______________________________________________
>>>> swift-evolution mailing list
>>>> [email protected] <mailto:[email protected]>
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>> _______________________________________________
>>> swift-evolution mailing list
>>> [email protected] <mailto:[email protected]>
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected] <mailto:[email protected]>
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>
> _______________________________________________
> swift-evolution mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution