[Pitch] Introducing the "Unwrap or Die" operator to the standard library

Noted and will incorporate into updated text

Thanks, -- E

···

On Jun 28, 2017, at 3:46 PM, Jordan Rose <jordan_rose@apple.com> wrote:

On Jun 28, 2017, at 14:40, Erica Sadun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

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."

Note that 'unsafelyUnwrapped' does not perform the check in optimized builds (like 'assert'), while '!' does (like 'precondition'). If we go with '!!', it should behave like 'precondition', not 'assert'.

Jordan

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*.

···

On Wed, Jun 28, 2017 at 11:15 AM Dave DeLong <delong@apple.com> wrote:

On Jun 28, 2017, at 10:44 AM, Adrian Zubarev via swift-evolution < > swift-evolution@swift.org> wrote:

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 (
swift-evolution@swift.org) 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 < >> swift-evolution@swift.org> 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 < >>> swift-evolution@swift.org> wrote:

On Jun 28, 2017, at 8:27 AM, David Hart via swift-evolution < >>> swift-evolution@swift.org> 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
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

I'm unconvinced. We already have the perfectly functional "unwrap or die"
operator, that is, the *force unwrap* *! *operator.

Can it be improved? Definitely. If the developer wants to provide some
context for a possible fatal error, it would be great for the language to
give the tools to express it.

Perhaps we can examine a more general problem of improving debugging output
for symbols and operations. We can already associate some information with
functions and classes using the documentation markup. Why not build on that?

One could, for example, extend the existing* documentation markup sign*
*///* to pick up text as force unwrap messages:

    `let last = array.last! /// Array guaranteed non-empty`

Best,
Ilya.

···

On Wed, Jun 28, 2017 at 11:00 PM Erica Sadun via swift-evolution < swift-evolution@swift.org> 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

*> "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
removedwhen 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 < > swift-evolution@swift.org> wrote:

On Wed, Jun 28, 2017 at 11:15 AM Dave DeLong <delong@apple.com> wrote:

On Jun 28, 2017, at 10:44 AM, Adrian Zubarev via swift-evolution < >> swift-evolution@swift.org> 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 (
swift-evolution@swift.org) 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 < >>> swift-evolution@swift.org> 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 < >>>> swift-evolution@swift.org> wrote:

On Jun 28, 2017, at 8:27 AM, David Hart via swift-evolution < >>>> swift-evolution@swift.org> 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
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________

swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Okay, I’m starting to get on board with !!, but (remaining follows inline):

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

> "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`

I’d still like a () -> Never override to provide customisation:

let last = array.last !! logAndTrap(“Array guaranteed non-empty”)

···

On 28 Jun 2017, at 22:30, Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:

- 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 <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Wed, Jun 28, 2017 at 11:15 AM Dave DeLong <delong@apple.com <mailto:delong@apple.com>> wrote:

On Jun 28, 2017, at 10:44 AM, Adrian Zubarev via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> 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 (swift-evolution@swift.org <mailto:swift-evolution@swift.org>) 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 <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> 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 <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Jun 28, 2017, at 8:27 AM, David Hart via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> 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
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Exactly, that’s what I was aiming for by the `@autoclosure () -> Never`.

PS: I want to apologize for tons of typos I made in my last post. Just realized it now :/

···

--
Adrian Zubarev
Sent with Airmail

Am 28. Juni 2017 um 20:42:38, Tony Allevato (tony.allevato@gmail.com) schrieb:

On Wed, Jun 28, 2017 at 11:15 AM Dave DeLong <delong@apple.com> wrote:
On Jun 28, 2017, at 10:44 AM, Adrian Zubarev via swift-evolution <swift-evolution@swift.org> 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 (swift-evolution@swift.org) 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 <swift-evolution@swift.org> 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 <swift-evolution@swift.org> wrote:

On Jun 28, 2017, at 8:27 AM, David Hart via swift-evolution <swift-evolution@swift.org> 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
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Besides all that Never as a bottom type means that you can use fatalError() literally everywhere not only on the RHS of ??.

func foo(_: Int) {}

foo(fatalError())
That said, we can kill our application everywhere we would ever imagine, regardless of whether there is ? or ! operator present somewhere.

···

--
Adrian Zubarev
Sent with Airmail

Am 28. Juni 2017 um 23:50:18, Jaden Geller via swift-evolution (swift-evolution@swift.org) schrieb:

I’m strongly against not using the `??` operator for `x ?? fatalError()` since that is naturally what will be possible once the `Never` type is a real bottom type. If you want to use `!!` for the `x !! “bad things!”` convenience form, I don’t care. But the `Never` form should definitely, definitely use `??`.

On Jun 28, 2017, at 1:30 PM, Erica Sadun via swift-evolution <swift-evolution@swift.org> 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

"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 <swift-evolution@swift.org> wrote:

On Wed, Jun 28, 2017 at 11:15 AM Dave DeLong <delong@apple.com> wrote:
On Jun 28, 2017, at 10:44 AM, Adrian Zubarev via swift-evolution <swift-evolution@swift.org> 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 (swift-evolution@swift.org) 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 <swift-evolution@swift.org> 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 <swift-evolution@swift.org> wrote:

On Jun 28, 2017, at 8:27 AM, David Hart via swift-evolution <swift-evolution@swift.org> 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
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

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 <swift-evolution@swift.org> 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

> "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 <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Wed, Jun 28, 2017 at 11:15 AM Dave DeLong <delong@apple.com <mailto:delong@apple.com>> wrote:

On Jun 28, 2017, at 10:44 AM, Adrian Zubarev via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> 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 (swift-evolution@swift.org <mailto:swift-evolution@swift.org>) 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 <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> 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 <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Jun 28, 2017, at 8:27 AM, David Hart via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> 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
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

I realize that, which is why I’m strongly against this proposal. I could potentially be for adding the `??` overload temporarily, but I don’t really feel it is necessary either.

···

On Jun 28, 2017, at 2:55 PM, Adrian Zubarev <adrian.zubarev@devandartist.com> wrote:

Besides all that Never as a bottom type means that you can use fatalError() literally everywhere not only on the RHS of ??.

func foo(_: Int) {}

foo(fatalError())
That said, we can kill our application everywhere we would ever imagine, regardless of whether there is ? or ! operator present somewhere.

--
Adrian Zubarev
Sent with Airmail

Am 28. Juni 2017 um 23:50:18, Jaden Geller via swift-evolution (swift-evolution@swift.org <mailto:swift-evolution@swift.org>) schrieb:

I’m strongly against not using the `??` operator for `x ?? fatalError()` since that is naturally what will be possible once the `Never` type is a real bottom type. If you want to use `!!` for the `x !! “bad things!”` convenience form, I don’t care. But the `Never` form should definitely, definitely use `??`.

On Jun 28, 2017, at 1:30 PM, Erica Sadun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> 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

> "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 <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Wed, Jun 28, 2017 at 11:15 AM Dave DeLong <delong@apple.com <mailto:delong@apple.com>> wrote:

On Jun 28, 2017, at 10:44 AM, Adrian Zubarev via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> 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 (swift-evolution@swift.org <mailto:swift-evolution@swift.org>) 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 <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> 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 <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Jun 28, 2017, at 8:27 AM, David Hart via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> 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
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

I’m going to second this sentiment with the feeling that the message is seemingly redundant. It feels akin to the comment in this line of code:

    let value = 1 // This value is set to 1

On an error, one gets the trap with the optional unwrapped message, and goes to the code where they see what is being forced by assumption.

Does the message spelling out the code in natural language help?

Alan

···

On Jun 28, 2017, at 5:27 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

In the initial example, repeated here in largely identical form, the desired comment is "array must be non-empty." In what way does that provide more information than a bare `!`?

Perhaps I am misunderstanding, we should probably not focus on the content of the message, but rather that it exists at all.

Assuming that the fatal-error-with-message is useful, is it important to have a shorthand for this pattern built into the language?

If we think so, I believe the original proposal is the best solution so far, given the arguments against using ?? fatal…

Alan

···

On Jun 28, 2017, at 5:43 PM, Alan Westbrook via swift-evolution <swift-evolution@swift.org> wrote:

On Jun 28, 2017, at 5:27 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

In the initial example, repeated here in largely identical form, the desired comment is "array must be non-empty." In what way does that provide more information than a bare `!`?

I’m going to second this sentiment with the feeling that the message is seemingly redundant. It feels akin to the comment in this line of code:

    let value = 1 // This value is set to 1

On an error, one gets the trap with the optional unwrapped message, and goes to the code where they see what is being forced by assumption.

Does the message spelling out the code in natural language help?

By the same token, why does precondition have an optional string? Why would you ever want to write more than:

precondition(!array.isEmpty)

It’s self evident – the array must not be empty! Why the second argument?

Because you might want a meaningful string to be output when the app traps. And it gives you somewhere to document why it mustn’t be empty – the explanation for the precondition rather than the precondition itself. Similarly, when your app traps because of an unwrapped nil, it’s desirable to get some output in your debug console telling you why straight away, rather than have to hunt down the code, read the line that failed, then read the context around the line, to understand the reason. This is even more important if you didn’t write this code yourself.

Finally, there’s a woolier justification: there’s an often-touted misconception out there that force unwraps are bad, that they were only created to accommodate legacy apps, and that force-unwrapping is always bad and you should never do it. This isn’t true – there are many good reasons to use force unwrap (though if you reaching for it constantly it’s a bad sign). Force-unwrapping is often better than just whacking in a default value or optional chaining when the presence of nil would indicate a serious failure. Introduction of the `!!` operator could help endorse/encourage the use of “thoughtful” force-unwrapping, which often comes with a comment of the reasoning why it’s safe (of why the array can’t be empty at this point, not just that it is empty). And if you’re going to write a comment, why not make that comment useful for debugging at the same time.

In cases where it’s really not necessary, ! would remain just like, when you’re not really too fussed, you can leave off the string from a precondition.

···

On Jun 28, 2017, at 5:27 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

In the initial example, repeated here in largely identical form, the desired comment is "array must be non-empty." In what way does that provide more information than a bare `!`?

the reason why a function would return nil _are intended to be obvious, per the design rationale given in Swift project documents_.

The reason .last returns nil is obvious. But it doesn’t tell you anything about why the array itself should be non-empty at this point in the code.

I do not believe that "array must not be empty" or "array guaranteed non-empty" is such an example, and I cannot myself imagine another scenario where it would make such a difference.

As the screener of a non-zero number of radars resulting from unwrapped nils, I would certainly appreciate more use of guard let x = x else { fatalError(“explanation”) } and hope that !! would encourage it.

···

On Jun 28, 2017, at 6:32 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

That is why I changed it back to my "guarantee" version when replying:

guard !array.isEmpty else { ... }
/* ... */
let finalElement = array.last !! "Array guaranteed non-empty"

The expected unwrap behavior is clear and audited, even when other code appears between the guard statement and the explained forced unwrap.

As you point out, it's senseless to annotate a logical assertion known to be true ("must be non-empty") unless that annotation enhances the expression of why and how this otherwise dangerous operation is taking place. That explanation forms the mission statement of the `!!` operator.

By explaining, the `!!` operator differs from the direct use of `!`. It explains a fact known to hold true that allows the lhs to safely unwrap. It provides this in a way that is succinct and readable. It naturally moves with the line of code it is part of. The adoption of `!!` has already broadly been integrated into any number idiomatic libraries. Coders have done so to differentiate an audited known fact from the stray `!`, which may or may not be followed by a comment.

One last point: it is not the mission of document comments to provide any role beyond annotation. They are not there to guarantee preconditions, assertions, or any other behavioral contracts. They merely document.

-- Erica

···

On Jun 28, 2017, at 6:26 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Wed, Jun 28, 2017 at 5:05 PM, ilya via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
One could, for example, extend the existing documentation markup sign /// to pick up text as force unwrap messages:

    `let last = array.last! /// Array guaranteed non-empty`

I did not call this out initially, but I feel like this is an important point to address:

In the initial example, repeated here in largely identical form, the desired comment is "array must be non-empty." In what way does that provide more information than a bare `!`?

I have replied to another email but will repeat the point here: The proposed `!!` operator differs from the direct use of `!` in that it explains a fact known to hold true, allowing the lhs to safely unwrap.

The alternatives are:

* forced unwrap -- comments do not transfer to runtime, which leads coders to use:
* using guard with fatalError -- the !! operator provides an elegant sugared shortcut for this common code

-- E

···

On Jun 28, 2017, at 6:43 PM, Alan Westbrook via swift-evolution <swift-evolution@swift.org> wrote:

On Jun 28, 2017, at 5:27 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

In the initial example, repeated here in largely identical form, the desired comment is "array must be non-empty." In what way does that provide more information than a bare `!`?

I’m going to second this sentiment with the feeling that the message is seemingly redundant. It feels akin to the comment in this line of code:

    let value = 1 // This value is set to 1

On an error, one gets the trap with the optional unwrapped message, and goes to the code where they see what is being forced by assumption.

Does the message spelling out the code in natural language help?

Alan

I'm unconvinced. We already have the perfectly functional "unwrap or die"
operator, that is, the *force unwrap* *! *operator.

Can it be improved? Definitely. If the developer wants to provide some
context for a possible fatal error, it would be great for the language to
give the tools to express it.

Perhaps we can examine a more general problem of improving debugging
output for symbols and operations. We can already associate some
information with functions and classes using the documentation markup. Why
not build on that?

One could, for example, extend the existing* documentation markup sign*
*///* to pick up text as force unwrap messages:

    `let last = array.last! /// Array guaranteed non-empty`

I did not call this out initially, but I feel like this is an important
point to address:

In the initial example, repeated here in largely identical form, the
desired comment is "array must be non-empty." In what way does that provide
more information than a bare `!`?

To my mind, when you unwrap an optional, the reason for failure is evident:
you expected some value, but you got no value. Moreover, the document about
error handling design in Swift (available in the GitHub repo) explains that
functions should return nil (vs. throwing) _when there's only one (obvious)
way to fail_. Therefore, when you force-unwrap the subsequent result and
trap, there's been an obvious failure when you expected none. As far as I
can see, the overall logic behind such a design works together to obviate
the need for more explanation when force-unwrapping. The example above
demonstrates this point very well: when there is no last element of an
array, the array must be empty--this is, I'm sure all will agree, plainly
obvious and wisely modeled with an optional--and therefore, if you
encounter a fatal error unwrapping the result, you expected a non-empty
array and instead encountered an empty array.

As a result, I find Ilya's point to be very illuminating that `!` is _the_
force-unwrap-or-die operator. Can someone come up with a more plausible
motivation for an additional operator?

···

On Wed, Jun 28, 2017 at 5:05 PM, ilya via swift-evolution < swift-evolution@swift.org> wrote:

Best,
Ilya.

On Wed, Jun 28, 2017 at 11:00 PM Erica Sadun via swift-evolution < > swift-evolution@swift.org> 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

*> "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
removedwhen 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 < >> swift-evolution@swift.org> wrote:

On Wed, Jun 28, 2017 at 11:15 AM Dave DeLong <delong@apple.com> wrote:

On Jun 28, 2017, at 10:44 AM, Adrian Zubarev via swift-evolution < >>> swift-evolution@swift.org> 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 (
swift-evolution@swift.org) 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 < >>>> swift-evolution@swift.org> 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 < >>>>> swift-evolution@swift.org> wrote:

On Jun 28, 2017, at 8:27 AM, David Hart via swift-evolution < >>>>> swift-evolution@swift.org> 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
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________

swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

It may not be though. How many times have you seen a force unwrap and immediately thought the programmer to just be lazy, or new to Swift?

The !! syntax proposal at least makes these forces clearly an intentional and thought out endeavor.

Alan

···

On Jun 28, 2017, at 6:38 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

Sorry, I fail to see how either wording enhances the expression of why this operation is taking place. The entire explanation seems self-evident to me in `!`.

In the initial example, repeated here in largely identical form, the
desired comment is "array must be non-empty." In what way does that provide
more information than a bare `!`?

By the same token, why does precondition have an optional string? Why
would you ever want to write more than:

precondition(!array.isEmpty)

It’s self evident – the array must not be empty! Why the second argument?

In the case of `!array.isEmpty`, I would never use the second argument
precisely because that condition is self-documenting. As to the larger
question of why `precondition` is overloaded to take a second argument, my
understanding--reflected in how I use it--is that it is useful when the
meaning of the precondition is less than glanceable and cannot (without
significant effort on the part of the reader) reveal a human-readable
explanation as to _why_ the precondition might fail. However, as I
mentioned, the act of unwrapping an optional and the reason why a function
would return nil _are intended to be obvious, per the design rationale
given in Swift project documents_.

Because you might want a meaningful string to be output when the app
traps. And it gives you somewhere to document *why* it mustn’t be empty –
the explanation for the precondition rather than the precondition itself.
Similarly, when your app traps because of an unwrapped nil, it’s desirable
to get some output in your debug console telling you why straight away,
rather than have to hunt down the code, read the line that failed, then
read the context around the line, to understand the reason. This is even
more important if you didn’t write this code yourself.

I would like to see an example where this string plausibly makes the
difference between having to hunt down the code and not have to do so. I do
not believe that "array must not be empty" or "array guaranteed non-empty"
is such an example, and I cannot myself imagine another scenario where it
would make such a difference.

Finally, there’s a woolier justification: there’s an often-touted
misconception out there that force unwraps are bad, that they were only
created to accommodate legacy apps, and that force-unwrapping is always bad
and you should never do it. This isn’t true – there are many good reasons
to use force unwrap (though if you reaching for it constantly it’s a bad
sign). Force-unwrapping is often better than just whacking in a default
value or optional chaining when the presence of nil would indicate a
serious failure. Introduction of the `!!` operator could help
endorse/encourage the use of “thoughtful” force-unwrapping, which often
comes with a comment of the reasoning why it’s safe (of why the array can’t
be empty at this point, not just that it is empty). And if you’re going to
write a comment, why not make that comment useful for debugging at the same
time.

In cases where it’s really not necessary, ! would remain just like, when
you’re not really too fussed, you can leave off the string from a
precondition.

I am not sure this second argument is a winning one, in that it does
nothing to convince me that the RHS string is necessary. If the issue to be
addressed is that `!` is used too lightly and without thought, an equally
optimal result would be achieved by devising a new postfix operator `!!!`,
to be named the "thoughtful force-unwrapping operator," which is purely a
synonym for `!`.

···

On Wed, Jun 28, 2017 at 8:18 PM, Ben Cohen <ben_cohen@apple.com> wrote:

On Jun 28, 2017, at 5:27 PM, Xiaodi Wu via swift-evolution < > swift-evolution@swift.org> wrote:

One could, for example, extend the existing* documentation markup sign*
*///* to pick up text as force unwrap messages:

    `let last = array.last! /// Array guaranteed non-empty`

I did not call this out initially, but I feel like this is an important
point to address:

In the initial example, repeated here in largely identical form, the
desired comment is "array must be non-empty." In what way does that provide
more information than a bare `!`?

That is why I changed it back to my "*guarantee*" version when replying:

guard !array.isEmpty else { ... }
/* ... */
let finalElement = array.last !! "Array guaranteed non-empty"

The expected unwrap behavior is clear and audited, even when other code
appears between the guard statement and the explained forced unwrap.

As you point out, it's senseless to annotate a logical assertion known to
be true ("must be non-empty") *unless that annotation enhances the
expression of why and how this otherwise dangerous operation is taking
place*. That explanation forms the mission statement of the `!!` operator.

Sorry, I fail to see how either wording enhances the expression of why this
operation is taking place. The entire explanation seems self-evident to me
in `!`.

By explaining, the `!!` operator differs from the direct use of `!`. It
explains a fact known to hold true that allows the lhs to safely unwrap. It
provides this in a way that is succinct and readable. It naturally moves
with the line of code it is part of. The adoption of `!!` has already
broadly been integrated into any number idiomatic libraries. Coders have
done so to differentiate an *audited known fact* from the stray `!`,
which may or may not be followed by a comment.

_Every_ use of `!` is an assertion that it is an audited known fact that
the operand is not nil. What I'm saying is that, so far in this
conversation, I have seen no example where any other known fact on the RHS
of your proposed operator is not trivially deducible from the built-in
known fact signified by `!` itself.

One last point: it is not the mission of document comments to provide any

···

On Wed, Jun 28, 2017 at 8:13 PM, Erica Sadun <erica@ericasadun.com> wrote:

On Jun 28, 2017, at 6:26 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:
On Wed, Jun 28, 2017 at 5:05 PM, ilya via swift-evolution < > swift-evolution@swift.org> wrote:
role beyond annotation. They are not there to guarantee preconditions,
assertions, or any other behavioral contracts. They merely document.

-- Erica

You needn’t imagine. There was one up-thread:

  let paramData = params.data(using: String.Encoding.ascii)!

Huh? Why is force unwrap safe here? OK, the code plainly says the author thinks that `params` must already be ASCII, but why is that a safe assumption? What reasoning lead to that? What other sections of the code does that reasoning depend on? If we get a crash on this line of code, what chain of assumptions should we follow to discover the change that broke the original author’s reasoning behind the force unwrap?

This is a job for a comment:

  let paramData = params.data(using: String.Encoding.ascii)! // params is URL-escaped, thus already ASCII

Aha, it’s URL escaped.

That comment does not repeat information already stated in the code itself. It does what any good comment does: it explains intent, context, and rationale. It doesn’t restate _what_, but rather explains _why_.

For those who appreciate comments like that, this proposal simply allows them to surface at runtime:

  let paramData = params.data(using: String.Encoding.ascii) !! "params is URL-escaped, thus already ASCII"

And those who see no value in such a runtime message — and thus likely also see no value such a comment — are free not to use either.

Cheers,

Paul

···

On Jun 28, 2017, at 8:32 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I would like to see an example where this string plausibly makes the difference between having to hunt down the code and not have to do so. I do not believe that "array must not be empty" or "array guaranteed non-empty" is such an example, and I cannot myself imagine another scenario where it would make such a difference.

I would like to see an example where this string plausibly makes the
difference between having to hunt down the code and not have to do so. I do
not believe that "array must not be empty" or "array guaranteed non-empty"
is such an example, and I cannot myself imagine another scenario where it
would make such a difference.

You needn’t imagine. There was one up-thread:

  let paramData = params.data(using: String.Encoding.ascii)!

Huh? Why is force unwrap safe here? OK, the code plainly says the author
thinks that `params` must already be ASCII, but why is that a safe
assumption? What reasoning lead to that? What other sections of the code
does that reasoning depend on? If we get a crash on this line of code, what
chain of assumptions should we follow to discover the change that broke the
original author’s reasoning behind the force unwrap?

This is a job for a comment:

  let paramData = params.data(using: String.Encoding.ascii)! // params
is URL-escaped, thus already ASCII

Aha, it’s URL escaped.

That comment does not repeat information already stated in the code
itself. It does what any good comment does: it explains intent, context,
and rationale. It doesn’t restate _what_, but rather explains _why_.

For those who appreciate comments like that, this proposal simply allows
them to surface at runtime:

  let paramData = params.data(using: String.Encoding.ascii) !! "params is URL-escaped,
thus already ASCII"

And those who see no value in such a runtime message — and thus likely
also see no value such a comment — are free not to use either.

If this is the most convincing example, then I'd actually be adamantly
_against_ such an operator (where now I'm merely skeptical and would like
to see evidence of usefulness). This example is, quite simply, _wrong_.
Here's why:

First, if force unwrapping fails, the message should explain why it failed:
the reason why it failed is _not_ because it's URL-escaped and _not_
because it's ASCII, but rather because it's **not** ASCII.

Second, even supposing the wording were fixed, it's at best not more useful
than `!` and at worst misleading. If the error message is "params not
ASCII-encoded" then it restates the code itself. If the error message is
"params not URL-escaped," then it's misleading, as that's not at all what
the LHS is actually asserting: it can be unwrapped *whether or not* it's
URL-escaped and it only matters that it's ASCII. You **absolutely cannot**
proceed from this point in the code assuming that `paramData` is a
URL-escaped string.

···

On Wed, Jun 28, 2017 at 8:54 PM, Paul Cantrell <paul@bustoutsolutions.com> wrote:

On Jun 28, 2017, at 8:32 PM, Xiaodi Wu via swift-evolution < > swift-evolution@swift.org> wrote:

Cheers,

Paul