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]> 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] > https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
