[swift-evolution] [Pre-Draft] Nil-coalescing and errors

Pyry Jahkola pyry.jahkola at iki.fi
Wed Apr 6 12:35:46 CDT 2016

>>> Interesting, but I’m unsure if all of it is significantly better than just using the guard that is effectively inside of the operator/func that is being proposed:
>>> guard let value = Int("NotANumber") else { throw InitializerError.invalidString }
>> That is a pretty damn compelling argument.

Made me smile too. :-)

> For some cases, yes. For others…

Right. Continuing that thought, Swift is not a language where there's exactly one way of doing everything. For `Optional` unwrapping, we have `if let`, `guard let`, `x.map(f)`, `x.flatMap(f)`, `x?.member`, `x ?? y`, and a bunch of others. The fact that you can already do almost the same thing with a statement doesn't rule out the occasional need to do the same thing in just an expression.

But like it was said, it's pretty easy to add this in a user-defined extension too, so it remains a question of whether people in general see `x ??? error` or `x.orThrow(error)` as a useful thing to have.

> 	myInt = Int("NotANumber") ?? throw InitializerError.invalidString

The following works already:

	myInt = Int("NotANumber") ?? { throw InitializerError.invalidString }()

(Ping Erica, to the list of alternatives considered.)

> On the other hand, all we really need is a generalized "noneMap" function marked as rethrowing, which can serve multiple purposes.
> 	myOtherInt = Int("NotANumber").noneMap(arc4random)
> 	myInt = try Int("NotANumber").noneMap { throw InitializerError.invalidString }

If I got it right, you're after this extension:

	extension Optional {
	    func noneMap(ifNone: () throws -> Wrapped) rethrows -> Wrapped {
	        return try self ?? ifNone()

Since we have `??` already, I feel `noneMap` isn't different enough to justify being added to the standard library.

> On the gripping hand: I think this is only a problem because `throw` is a statement, not an expression. Could it be changed to be an expression with an unspecified return type? I believe that would allow you to simply drop it into the right side of a ?? operator, and anywhere else you might want it (boolean operators, for instance).

Why not. That's essentially making the `x ?? raise(error)` trick into a language feature. My guts say people wouldn't like how it looks. Would've suggested that as another option otherwise.

All in all, I think the error handling model introduced in Swift 2.0 was pretty heavy on syntax compared to how much new functionality it made possible (and even now, we don't have catch exhaustiveness checking or asynchronous error handling, to name a few). I'd rather improve Swift's error handling by introducing features on the library side and only inventing new syntax for things that can't be done in code.

— Pyry

More information about the swift-evolution mailing list