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


(Erica Sadun) #1

Using an operator to provide feedback on the context of a failed unwrap has become a commonly implemented approach in the Swift developer Community. What are your thoughts about adopting this widely-used operator into the standard library?

guard !lastItem.isEmpty else { return }
let lastItem = array.last !! "Array must be non-empty"

Details here: https://gist.github.com/erica/423e4b1c63b95c4c90338cdff4939a9b

Thank you for your thoughtful feedback, -- E


Resolved: Insert "!" is a bad fixit
(Jaden Geller) #2

I like this idea, but I like idea of treating `Never` as a bottom type more. This would allow other `Never`-returning functions like `preconditionFailure` to be used as well.

let x = y ?? preconditonFailure("reason")

This also avoids the issue of `!!` needing `file` and `line` arguments.

Cheers,
Jaden Geller

···

On Jun 27, 2017, at 10:16 AM, Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:

Using an operator to provide feedback on the context of a failed unwrap has become a commonly implemented approach in the Swift developer Community. What are your thoughts about adopting this widely-used operator into the standard library?

guard !lastItem.isEmpty else { return }
let lastItem = array.last !! "Array must be non-empty"

Details here: https://gist.github.com/erica/423e4b1c63b95c4c90338cdff4939a9b

Thank you for your thoughtful feedback, -- E

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


(Zachary Waldowski) #3

Big +1.

Using `!` is widely seen as a smell. However, the need for it still
arises; they are preconditions, of a sort. It has become prevalent in my
teams’ codebases to do “guard else preconditionFailure”.
I like `!!` over something like `?!`; it follows the pattern that almost
every `?` in the language has an equivalent `!`.
The implementation details are ultimately not relevant to me. I’m a fan
of `Never` being a bottom type for more reasons than just this. I also
see no reason why operator funcs couldn’t accept file and line as extra
arguments on the rhs.
Best,
  Zachary Waldowski
  zach@waldowski.me

On Tue, Jun 27, 2017, at 01:16 PM, Erica Sadun via swift-evolution wrote:> Using an operator to provide feedback on the context of a failed

···

unwrap has become a commonly implemented approach in the Swift
developer Community. What are your thoughts about adopting this widely-
used operator into the standard library?>
guard !lastItem.isEmpty else { return }
let lastItem = array.last !! "Array must be non-empty"

Details here:
https://gist.github.com/erica/423e4b1c63b95c4c90338cdff4939a9b>
Thank you for your thoughtful feedback, -- E

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


(Xiaodi Wu) #4

As you write, this operator becomes sugar for “?? fatalError()” once Never
becomes a true bottom type.

In the meantime, can’t the same thing be accomplished by overloading
fatalError so it’s a generic function that returns a discardable result of
type T, which in turn calls the Never-returning overload?

···

On Tue, Jun 27, 2017 at 12:25 Erica Sadun via swift-evolution < swift-evolution@swift.org> wrote:

Using an operator to provide feedback on the context of a failed unwrap
has become a commonly implemented approach in the Swift developer
Community. What are your thoughts about adopting this widely-used operator
into the standard library?

guard !lastItem.isEmpty else { return }
let lastItem = array.last !! "Array must be non-empty"

Details here:
https://gist.github.com/erica/423e4b1c63b95c4c90338cdff4939a9b

Thank you for your thoughtful feedback, -- E

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


(Adrian Zubarev) #5

+1 I had a slightly different implementation.

https://gist.github.com/DevAndArtist/dad641ee833e60b02fd1db2dbb488c6a

//
// UnwrapOrTrap.swift
//
infix operator ?! : NilCoalescingPrecedence

/// Performs a nil-coalescing operation, returning the wrapped value of an
/// `Optional` instance or uses the rhs function to stop the program.
///
/// - Parameters:
/// - optional: An optional value.
/// - noreturn: A function to stop the programm.
func ?!<T>(optional: T?, noreturn: @autoclosure () -> Never) -> T {
   switch optional {
   case .some(let value):
      return value
   case .none:
      noreturn()
   }
}

···

--
Adrian Zubarev
Sent with Airmail

Am 27. Juni 2017 um 19:25:15, Erica Sadun via swift-evolution (swift-evolution@swift.org) schrieb:

Using an operator to provide feedback on the context of a failed unwrap has become a commonly implemented approach in the Swift developer Community. What are your thoughts about adopting this widely-used operator into the standard library?

guard !lastItem.isEmpty else { return }
let lastItem = array.last !! "Array must be non-empty"

Details here: https://gist.github.com/erica/423e4b1c63b95c4c90338cdff4939a9b

Thank you for your thoughtful feedback, -- E

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


(Rien) #6

I would not use it.
Somehow it gives me the creeps to leave something like ‘fatalError’ in a shipping application.
During development it could make sense, but then again I like to keep development and shipping the same as much as possible.

Regards,
Rien

Site: http://balancingrock.nl
Blog: http://swiftrien.blogspot.com
Github: http://github.com/Balancingrock
Project: http://swiftfire.nl - An HTTP(S) web server framework in Swift

···

On 27 Jun 2017, at 19:16, Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:

Using an operator to provide feedback on the context of a failed unwrap has become a commonly implemented approach in the Swift developer Community. What are your thoughts about adopting this widely-used operator into the standard library?

guard !lastItem.isEmpty else { return }
let lastItem = array.last !! "Array must be non-empty"

Details here: https://gist.github.com/erica/423e4b1c63b95c4c90338cdff4939a9b

Thank you for your thoughtful feedback, -- E

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


(Yuta Koshizawa) #7

I like it, but I think the implementation can be improved like below.

    public static func !!(optional: Optional, errorMessage:
@autoclosure () -> String) -> Wrapped {
        precondition(optional != nil, errorMessage())
        return optional!
    }

Failures of forced unwrapping are "logic failures" and I think it is
same about `!!`.

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.

So I think checks for `!!` should be removed with `-Ounchecked` as well.

···

--
Yuta

2017-06-28 2:16 GMT+09:00 Erica Sadun via swift-evolution <swift-evolution@swift.org>:

Using an operator to provide feedback on the context of a failed unwrap has
become a commonly implemented approach in the Swift developer Community.
What are your thoughts about adopting this widely-used operator into the
standard library?

guard !lastItem.isEmpty else { return }
let lastItem = array.last !! "Array must be non-empty"

Details here:
https://gist.github.com/erica/423e4b1c63b95c4c90338cdff4939a9b

Thank you for your thoughtful feedback, -- E

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


(Brent Royal-Gordon) #8

Finally found a few minutes to read this thread.

I'm a big fan of the `Never`-based approach. (I was before, but I am more so now.) Here are the points I can see in its favor:

1. It is extremely clear about what's happening—`!!` is another random operator to learn, but `fatalError(_:)` or `preconditionFailure(_:)` are fairly self-explanatory, and `??` is something you might already be using.

2. It allows you to control the optimization behavior by using `fatalError`, `preconditionFailure`, or `assertionFailure` as desired.

3. If we later change `throw` from being a statement to being a `Never`-returning expression, you could use `throw` on the right-hand side of `??`.

4. It supports other `Never`-returning operations, like `abort()` or `exit(_:)` or your custom `usage()` function, on the right side of `??`.

5. It supports file-and-line error reporting without having to add any new features; `!!` could not do this because an operator can't have extra, defaulted parameters to carry the file and line.

6. It harmonizes with the eventual idea of making `Never` a universal bottom type, but we don't actually have to implement that today, because we can just overload `??` for now.

Against these advantages, the only one I can see for `!!` is that it is terse. Terseness is good, especially for a feature which is competing with the single-character postfix `!` operator, but I can't help but be drawn to the flexibility and power of `??` with a `Never` expression on the right-hand side.

···

On Jun 27, 2017, at 10:16 AM, Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:

Using an operator to provide feedback on the context of a failed unwrap has become a commonly implemented approach in the Swift developer Community. What are your thoughts about adopting this widely-used operator into the standard library?

guard !lastItem.isEmpty else { return }
let lastItem = array.last !! "Array must be non-empty"

Details here: https://gist.github.com/erica/423e4b1c63b95c4c90338cdff4939a9b

Thank you for your thoughtful feedback, -- E

--
Brent Royal-Gordon
Architechies


(Jacob Bandes-Storch) #9

I've found a similar thing useful, but with Errors instead of fatalErroring:

infix operator ?! : NilCoalescingPrecedence

func ?!<T>(lhs: T?, rhs: @autoclosure () -> Error) throws -> T {
    if let lhs = lhs { return lhs }
    throw rhs()
}

let x = try failableFunc() ?! MyError.somethingFailed

···

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

+1 I had a slightly different implementation.

https://gist.github.com/DevAndArtist/dad641ee833e60b02fd1db2dbb488c6a

//
// UnwrapOrTrap.swift
//
infix operator ?! : NilCoalescingPrecedence

/// Performs a nil-coalescing operation, returning the wrapped value of an
/// `Optional` instance or uses the rhs function to stop the program.
///
/// - Parameters:
/// - optional: An optional value.
/// - noreturn: A function to stop the programm.
func ?!<T>(optional: T?, noreturn: @autoclosure () -> Never) -> T {
   switch optional {
   case .some(let value):
      return value
   case .none:
      noreturn()
   }
}

--
Adrian Zubarev
Sent with Airmail

Am 27. Juni 2017 um 19:25:15, Erica Sadun via swift-evolution (
swift-evolution@swift.org) schrieb:

Using an operator to provide feedback on the context of a failed unwrap
has become a commonly implemented approach in the Swift developer
Community. What are your thoughts about adopting this widely-used operator
into the standard library?

guard !lastItem.isEmpty else { return }
let lastItem = array.last !! "Array must be non-empty"

Details here: https://gist.github.com/erica/
423e4b1c63b95c4c90338cdff4939a9b

Thank you for your thoughtful feedback, -- E

_______________________________________________
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


(Jacob Williams) #10

+1 to Adrians implementation. While I like the sugar of both, I don’t think the operator should necessarily always cause a fatalError. Maybe we could use both the !! For some kind of fatal error and Adrians !? To just use @noreturn to leave the current function.

···

On Jun 27, 2017, at 11:29 AM, Adrian Zubarev via swift-evolution <swift-evolution@swift.org> wrote:

+1 I had a slightly different implementation.

https://gist.github.com/DevAndArtist/dad641ee833e60b02fd1db2dbb488c6a
//
// UnwrapOrTrap.swift
//
infix operator ?! : NilCoalescingPrecedence

/// Performs a nil-coalescing operation, returning the wrapped value of an
/// `Optional` instance or uses the rhs function to stop the program.
///
/// - Parameters:
/// - optional: An optional value.
/// - noreturn: A function to stop the programm.
func ?!<T>(optional: T?, noreturn: @autoclosure () -> Never) -> T {
   switch optional {
   case .some(let value):
      return value
   case .none:
      noreturn()
   }
}

--
Adrian Zubarev
Sent with Airmail

Am 27. Juni 2017 um 19:25:15, Erica Sadun via swift-evolution (swift-evolution@swift.org <mailto:swift-evolution@swift.org>) schrieb:

Using an operator to provide feedback on the context of a failed unwrap has become a commonly implemented approach in the Swift developer Community. What are your thoughts about adopting this widely-used operator into the standard library?

guard !lastItem.isEmpty else { return }
let lastItem = array.last !! "Array must be non-empty"

Details here: https://gist.github.com/erica/423e4b1c63b95c4c90338cdff4939a9b

Thank you for your thoughtful feedback, -- E

_______________________________________________
swift-evolution mailing list
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


(Dave DeLong) #11

Also a +1 from me. This is something I always put in to my code.

I agree that having `Never` as a bottom type is interesting, but even if that were the case, the proposed “!!” operator is still useful, because it short-circuits having to fatalError() myself. IE:

let last = array.last ?? fatalError(“array must not be empty”)

vs

let last = array.last !! “Array must not be empty"

I also think having it “fatalError” in shipping code is fine, because it’s equivalent to what would happen if you incorrect force-unwrap.

Dave

···

On Jun 27, 2017, at 12:08 PM, Zach Waldowski via swift-evolution <swift-evolution@swift.org> wrote:

Big +1.

Using `!` is widely seen as a smell. However, the need for it still arises; they are preconditions, of a sort. It has become prevalent in my teams’ codebases to do “guard else preconditionFailure”.

I like `!!` over something like `?!`; it follows the pattern that almost every `?` in the language has an equivalent `!`.

The implementation details are ultimately not relevant to me. I’m a fan of `Never` being a bottom type for more reasons than just this. I also see no reason why operator funcs couldn’t accept file and line as extra arguments on the rhs.

Best,
  Zachary Waldowski
  zach@waldowski.me <mailto:zach@waldowski.me>

On Tue, Jun 27, 2017, at 01:16 PM, Erica Sadun via swift-evolution wrote:

Using an operator to provide feedback on the context of a failed unwrap has become a commonly implemented approach in the Swift developer Community. What are your thoughts about adopting this widely-used operator into the standard library?

guard !lastItem.isEmpty else { return }
let lastItem = array.last !! "Array must be non-empty"

Details here: https://gist.github.com/erica/423e4b1c63b95c4c90338cdff4939a9b

Thank you for your thoughtful feedback, -- E

_______________________________________________
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


(Max Moiseev) #12

As you write, this operator becomes sugar for “?? fatalError()” once Never becomes a true bottom type.

In the meantime, can’t the same thing be accomplished by overloading fatalError so it’s a generic function that returns a discardable result of type T, which in turn calls the Never-returning overload?

I like this idea more than adding an extra operator, but overloading fatalError won’t work now because of https://github.com/apple/swift/blob/master/stdlib/public/core/Optional.swift#L668

···

On Jun 27, 2017, at 10:38 AM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

On Tue, Jun 27, 2017 at 12:25 Erica Sadun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Using an operator to provide feedback on the context of a failed unwrap has become a commonly implemented approach in the Swift developer Community. What are your thoughts about adopting this widely-used operator into the standard library?

guard !lastItem.isEmpty else { return }
let lastItem = array.last !! "Array must be non-empty"

Details here: https://gist.github.com/erica/423e4b1c63b95c4c90338cdff4939a9b

Thank you for your thoughtful feedback, -- E

_______________________________________________
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


(Dave DeLong) #13

I agree with Jaden and Xiaodi above—making Never a proper bottom type and using ?? would accomplish the same thing, and it's more general because it doesn't imply fatalError.

IMO, I don't think we should be making it *easier* to hide traps in our code. I don't think having to write a full guard/fatalError is all that bad a thing—on the contrary, I want major failure points to stick out when I read code. That being said, if some users want something like this, Never + ?? would get us there with something already planned for the language, rather than introducing a new operator (for which the bar should be set high).

I disagree that this is making hiding traps easier. It’s asking you to put in two exclamation points instead of only one to force unwrap, along with an explanation of why you think it’s ok to be doing so. That’s much more “in your face” than “array.last!”.

Dave

···

On Jun 27, 2017, at 1:43 PM, Tony Allevato via swift-evolution <swift-evolution@swift.org> wrote:

On Tue, Jun 27, 2017 at 12:10 PM Paul Cantrell via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
> it gives me the creeps to leave something like ‘fatalError’ in a shipping application

Agreed, and I would use it for _exactly_ this reason.

I avoid force unwrapping in production code, looking first for ways to gracefully handle the situation. Whenever I do use !, there is careful reasoning behind its use: “this is safe because p → q, and there is no reasonable way to handle this error because it cannot happen.” I take care to note this reasoning in a same-line comment, e.g.:

   paramString.data(using: String.Encoding.ascii)! // ASCII safe because paramString already URL escaped

Such reasoning will, of course, eventually fail somewhere. It would be helpful to get runtime diagnostics on such a failure:

   paramString.data(using: String.Encoding.ascii) !! "URL escaped paramString must be ASCII"

So Rien, I endorse this idea from the perspective of one who is !-averse.

Cheers, P

> On Jun 27, 2017, at 12:44 PM, Rien via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>
> I would not use it.
> Somehow it gives me the creeps to leave something like ‘fatalError’ in a shipping application.
> During development it could make sense, but then again I like to keep development and shipping the same as much as possible.
>
> Regards,
> Rien
>
> Site: http://balancingrock.nl <http://balancingrock.nl/>
> Blog: http://swiftrien.blogspot.com <http://swiftrien.blogspot.com/>
> Github: http://github.com/Balancingrock
> Project: http://swiftfire.nl <http://swiftfire.nl/> - An HTTP(S) web server framework in Swift
>
>
>
>
>
>
>
>> On 27 Jun 2017, at 19:16, Erica Sadun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>>
>> Using an operator to provide feedback on the context of a failed unwrap has become a commonly implemented approach in the Swift developer Community. What are your thoughts about adopting this widely-used operator into the standard library?
>>
>> guard !lastItem.isEmpty else { return }
>> let lastItem = array.last !! "Array must be non-empty"
>>
>> Details here: https://gist.github.com/erica/423e4b1c63b95c4c90338cdff4939a9b
>>
>> Thank you for your thoughtful feedback, -- E
>>
>> _______________________________________________
>> 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


(Paul Cantrell) #14

it gives me the creeps to leave something like ‘fatalError’ in a shipping application

Agreed, and I would use it for _exactly_ this reason.

I avoid force unwrapping in production code, looking first for ways to gracefully handle the situation. Whenever I do use !, there is careful reasoning behind its use: “this is safe because p → q, and there is no reasonable way to handle this error because it cannot happen.” I take care to note this reasoning in a same-line comment, e.g.:

   paramString.data(using: String.Encoding.ascii)! // ASCII safe because paramString already URL escaped

Such reasoning will, of course, eventually fail somewhere. It would be helpful to get runtime diagnostics on such a failure:

   paramString.data(using: String.Encoding.ascii) !! "URL escaped paramString must be ASCII"

So Rien, I endorse this idea from the perspective of one who is !-averse.

Cheers, P

···

On Jun 27, 2017, at 12:44 PM, Rien via swift-evolution <swift-evolution@swift.org> wrote:

I would not use it.
Somehow it gives me the creeps to leave something like ‘fatalError’ in a shipping application.
During development it could make sense, but then again I like to keep development and shipping the same as much as possible.

Regards,
Rien

Site: http://balancingrock.nl
Blog: http://swiftrien.blogspot.com
Github: http://github.com/Balancingrock
Project: http://swiftfire.nl - An HTTP(S) web server framework in Swift

On 27 Jun 2017, at 19:16, Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:

Using an operator to provide feedback on the context of a failed unwrap has become a commonly implemented approach in the Swift developer Community. What are your thoughts about adopting this widely-used operator into the standard library?

guard !lastItem.isEmpty else { return }
let lastItem = array.last !! "Array must be non-empty"

Details here: https://gist.github.com/erica/423e4b1c63b95c4c90338cdff4939a9b

Thank you for your thoughtful feedback, -- E

_______________________________________________
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


(Erica Sadun) #15

This ties in pretty closely with my goals for the "roles" proposal. I want Swift to evolve towards clarifying developer intent both for code inspection and compilation support.

I honestly wouldn't mind having both solutions available.

-- E

···

On Jun 27, 2017, at 1:51 PM, Dave DeLong via swift-evolution <swift-evolution@swift.org> wrote:

On Jun 27, 2017, at 1:43 PM, Tony Allevato via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I agree with Jaden and Xiaodi above—making Never a proper bottom type and using ?? would accomplish the same thing, and it's more general because it doesn't imply fatalError.

IMO, I don't think we should be making it *easier* to hide traps in our code. I don't think having to write a full guard/fatalError is all that bad a thing—on the contrary, I want major failure points to stick out when I read code. That being said, if some users want something like this, Never + ?? would get us there with something already planned for the language, rather than introducing a new operator (for which the bar should be set high).

I disagree that this is making hiding traps easier. It’s asking you to put in two exclamation points instead of only one to force unwrap, along with an explanation of why you think it’s ok to be doing so. That’s much more “in your face” than “array.last!”.

Dave


(Tony Allevato) #16

I agree with Jaden and Xiaodi above—making Never a proper bottom type and
using ?? would accomplish the same thing, and it's more general because it
doesn't imply fatalError.

IMO, I don't think we should be making it *easier* to hide traps in our
code. I don't think having to write a full guard/fatalError is all that bad
a thing—on the contrary, I want major failure points to stick out when I
read code. That being said, if some users want something like this, Never +
?? would get us there with something already planned for the language,
rather than introducing a new operator (for which the bar should be set
high).

···

On Tue, Jun 27, 2017 at 12:10 PM Paul Cantrell via swift-evolution < swift-evolution@swift.org> wrote:

> it gives me the creeps to leave something like ‘fatalError’ in a
shipping application

Agreed, and I would use it for _exactly_ this reason.

I avoid force unwrapping in production code, looking first for ways to
gracefully handle the situation. Whenever I do use !, there is careful
reasoning behind its use: “this is safe because p → q, and there is no
reasonable way to handle this error because it cannot happen.” I take care
to note this reasoning in a same-line comment, e.g.:

   paramString.data(using: String.Encoding.ascii)! // ASCII safe because
paramString already URL escaped

Such reasoning will, of course, eventually fail somewhere. It would be
helpful to get runtime diagnostics on such a failure:

   paramString.data(using: String.Encoding.ascii) !! "URL escaped
paramString must be ASCII"

So Rien, I endorse this idea from the perspective of one who is !-averse.

Cheers, P

> On Jun 27, 2017, at 12:44 PM, Rien via swift-evolution < > swift-evolution@swift.org> wrote:
>
> I would not use it.
> Somehow it gives me the creeps to leave something like ‘fatalError’ in a
shipping application.
> During development it could make sense, but then again I like to keep
development and shipping the same as much as possible.
>
> Regards,
> Rien
>
> Site: http://balancingrock.nl
> Blog: http://swiftrien.blogspot.com
> Github: http://github.com/Balancingrock
> Project: http://swiftfire.nl - An HTTP(S) web server framework in Swift
>
>
>
>
>
>
>
>> On 27 Jun 2017, at 19:16, Erica Sadun via swift-evolution < > swift-evolution@swift.org> wrote:
>>
>> Using an operator to provide feedback on the context of a failed unwrap
has become a commonly implemented approach in the Swift developer
Community. What are your thoughts about adopting this widely-used operator
into the standard library?
>>
>> guard !lastItem.isEmpty else { return }
>> let lastItem = array.last !! "Array must be non-empty"
>>
>> Details here:
https://gist.github.com/erica/423e4b1c63b95c4c90338cdff4939a9b
>>
>> Thank you for your thoughtful feedback, -- E
>>
>> _______________________________________________
>> 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


(David Hart) #17

Also a +1 from me. This is something I always put in to my code.

I agree that having `Never` as a bottom type is interesting, but even if that were the case, the proposed “!!” operator is still useful, because it short-circuits having to fatalError() myself. IE:

let last = array.last ?? fatalError(“array must not be empty”)

The above solution with Never is the better solution IMHO:

No new operator
More flexible: what if you want something else than a fatalError? For example, I might want to define a logAndFatalError() function which stores the error to a log file before trapping.

···

On 27 Jun 2017, at 20:23, Dave DeLong via swift-evolution <swift-evolution@swift.org> wrote:

vs

let last = array.last !! “Array must not be empty"

I also think having it “fatalError” in shipping code is fine, because it’s equivalent to what would happen if you incorrect force-unwrap.

Dave

On Jun 27, 2017, at 12:08 PM, Zach Waldowski via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Big +1.

Using `!` is widely seen as a smell. However, the need for it still arises; they are preconditions, of a sort. It has become prevalent in my teams’ codebases to do “guard else preconditionFailure”.

I like `!!` over something like `?!`; it follows the pattern that almost every `?` in the language has an equivalent `!`.

The implementation details are ultimately not relevant to me. I’m a fan of `Never` being a bottom type for more reasons than just this. I also see no reason why operator funcs couldn’t accept file and line as extra arguments on the rhs.

Best,
  Zachary Waldowski
  zach@waldowski.me <mailto:zach@waldowski.me>

On Tue, Jun 27, 2017, at 01:16 PM, Erica Sadun via swift-evolution wrote:

Using an operator to provide feedback on the context of a failed unwrap has become a commonly implemented approach in the Swift developer Community. What are your thoughts about adopting this widely-used operator into the standard library?

guard !lastItem.isEmpty else { return }
let lastItem = array.last !! "Array must be non-empty"

Details here: https://gist.github.com/erica/423e4b1c63b95c4c90338cdff4939a9b

Thank you for your thoughtful feedback, -- E

_______________________________________________
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


(Adrian Zubarev) #18

How about?

public func ?? <T>(optional: T?, noreturnOrError: @autoclosure () throws -> Never) rethrows -> T {
    switch optional {
    case .some(let value):
        return value
    case .none:
        try noreturnOrError()
    }
}

···

--
Adrian Zubarev
Sent with Airmail

Am 27. Juni 2017 um 21:54:57, Max Moiseev via swift-evolution (swift-evolution@swift.org) schrieb:

On Jun 27, 2017, at 10:38 AM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

As you write, this operator becomes sugar for “?? fatalError()” once Never becomes a true bottom type.

In the meantime, can’t the same thing be accomplished by overloading fatalError so it’s a generic function that returns a discardable result of type T, which in turn calls the Never-returning overload?

I like this idea more than adding an extra operator, but overloading fatalError won’t work now because of https://github.com/apple/swift/blob/master/stdlib/public/core/Optional.swift#L668

On Tue, Jun 27, 2017 at 12:25 Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:
Using an operator to provide feedback on the context of a failed unwrap has become a commonly implemented approach in the Swift developer Community. What are your thoughts about adopting this widely-used operator into the standard library?

guard !lastItem.isEmpty else { return }
let lastItem = array.last !! "Array must be non-empty"

Details here: https://gist.github.com/erica/423e4b1c63b95c4c90338cdff4939a9b

Thank you for your thoughtful feedback, -- E

_______________________________________________
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


(Elviro Rocca) #19

Yep, "logic" failures are not supposed to be there if not for avoiding checks that could worsen performance in pieces of code that should run as fast as possible. I like Adrian's solution because it doesn't add a new operator to the standard library, something that could mean one more encouragement to force unwrap things.

About preconditions, Cocoa with Love's Matt Gallagher wrote an article some months ago on partial functions, why you should avoid them and how to do so: it's a very interesting read http://www.cocoawithlove.com/blog/2016/01/25/partial-functions-part-one-avoidance.html

Elviro

···

Il giorno 28 giu 2017, alle ore 07:02, Yuta Koshizawa via swift-evolution <swift-evolution@swift.org> ha scritto:

...

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.

So I think checks for `!!` should be removed with `-Ounchecked` as well.

--
Yuta


(Yuta Koshizawa) #20

Hi, I think it is an orthogonal issue if we need a new operator. It is
also possible to introduce an infix `!` for it.

I am sure that we do not need to avoid `precondition` as long as we
use it appropriately. It is useful to realize consistent behavior with
`Array`'s `subscript`, forced unwrapping `!`, `&+` and so on. In this
context, `precondition` does not mean a general word "precondition"
but the `precondition` function in the Swift standard library, which
is removed when -Ounchecked.

However I noticed the possibility that -Ounchecked removed the `nil`
check by `??` in the following code using `preconditionFailure` as a
clue of the optimization.

    let bar: Foo = optionalFoo ?? preconditionFailure("Reason why you
are sure that `optionalFoo` is not nil")

So now I think using `?? preconditionFailure(message)` with `Never` as
a bottom type is preferable to `!!` even in a standpoint of
-Ounckecked.

···

--
Yuta

2017-06-28 15:52 GMT+09:00 Elviro Rocca <retired.hunter.djura@gmail.com>:

Yep, "logic" failures are not supposed to be there if not for avoiding
checks that could worsen performance in pieces of code that should run as
fast as possible. I like Adrian's solution because it doesn't add a new
operator to the standard library, something that could mean one more
encouragement to force unwrap things.

About preconditions, Cocoa with Love's Matt Gallagher wrote an article some
months ago on partial functions, why you should avoid them and how to do so:
it's a very interesting read
http://www.cocoawithlove.com/blog/2016/01/25/partial-functions-part-one-avoidance.html

Elviro

Il giorno 28 giu 2017, alle ore 07:02, Yuta Koshizawa via swift-evolution > <swift-evolution@swift.org> ha scritto:

...

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.

So I think checks for `!!` should be removed with `-Ounchecked` as well.

--
Yuta