[swift-evolution] [Pitch] Guard/Catch

Benjamin Spratling bspratling at mac.com
Sat Jul 8 13:14:50 CDT 2017

> func doSomething() throws → Result? { … }
> How would you handle both the catch and the let binding of the result?

I agree this proposal needs to define the behavior, since returning an optional from a throwing function is valid.

I see a few options:

1) find a way to generally incorporate optional binding and error binding into the same guard clause.
Could it be as simple as 
guard let result:Result = try doSomething()
catch { ...}
else { ... }

 In this option, the else block almost acts like "finally" block.  I recommend against this option because IF the developer has defined a function which returns nil and doesn't throw an error, they clearly intend for the nil to be a valid representation of state, and thus one the developer may wish to examine in more detail and potentially continue the function. I. E. Let's give the developer a chance to work with the nil value and not return.

2) Ignore it completely.  I.e. define the guard/catch pattern as not compatible with returning Optionals.  Throwing an error is usually considered an alternative to returning an optional, and importing Obj-C won't import throwing methods in this way. So I don't think prohibiting it is a totally absurd idea.  This makes it impossible for the developer to code and build code which accidentally does something he doesn't expect.

3) bind the optional value

Perhaps, when guard/catch-ing, an optional value is perfectly legal.

guard let result:Result? = try doSomething() catch ...
This is essentially how guard works with a try?today.
guard let result:Result? = try? doSomething() ...

In case 3, I think we have a potentially ambiguous behavior, because with type inference the programmer may expect that the value has also been optionally unwrapped.  Of course, he'll catch that later on in the function, but my concern is for the poor unwitting developer (such as myself) who is frustrated that his code doesn't compile and he doesn't understand why.  "But I did a guard let!   Why is it optional?!"  One option is to require the type be typed explicitly when guard/catching an optional, but I always type my types explicitly anyway, so I get that others may be more resistant to that idea.  Another option is to allow it, but just issue a warning until the developer adds the explicit type, such as requiring "self." in an escaping closure.  (Of course the compler can figure it out, this syntax is required so the developer can figure it out!)  Another option is for the smarts to be built in the the error/warning system to point out when an expression gets used as a non-optional when it came from a guard/catch to point it out, much as it points out the first instance of a function which has been defined twice.

 - Ben Spratling 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170708/bc087759/attachment.html>

More information about the swift-evolution mailing list