[swift-evolution] [Proposal]: Escaping another (unused) scope pyramide with 'guard try catch'

Félix Cloutier felixcca at yahoo.ca
Fri Feb 5 12:40:47 CST 2016


Unless you're declaring a variable with a single-statement try, there's no reason to disallow fallthrough.

Félix

> Le 5 févr. 2016 à 13:28:58, Adrian Zubarev via swift-evolution <swift-evolution at swift.org> a écrit :
> 
> Right now the error handling mechanism will fall through even if the error was handled inside the catch scope.
> 
> enum Error: ErrorType {
> 	case SomeError
> }
> 
> func throwingFunc() throws {
> 	throw Error.SomeError
> }
> 
> func throwingFuncReturns() throws -> Int {
> 	return 0
> }
> 
> do { try throwingFunc() } catch {
> 	/* do nothing */
> }
> 
> var num: Int
> do { num = try throwingFuncReturns() } catch {
> 	/* do nothing */
> }
> 
> print("both fell through")
> 
> To guarantee the safety of the execution from my point of view the catch body may not fall through (for single try statements), at least not by default.
> 
> I think it is fine to rename the proposed mechanism.
> 
> do try throwingFunc() catch { 
> 	/* handle error */ 
> }
> 
> do try throwingFunc() catch _ { 
> 	/* handle error */ 
> }
> 
> do try throwingFunc() catch pattern { 
> 	/* handle error */ 
> }
> 
> do try throwingFunc() catch pattern { 
> 	/* handle error */ 
> }
> 
> do let newInstance = try throwingFuncReturns() catch catch pattern where condition { 
> 	/* handle error */ 
> }
> 
> do var newMutableInstance = try throwingFuncReturns() catch pattern where condition { 
> 	/* handle error */ 
> }
> 
> 'Where' clause is significant for catching wider range of errors that might occur.
> 
> -- 
> Adrian Zubarev
> Sent with Airmail
> 
> Am 5. Februar 2016 bei 19:05:12, Félix Cloutier (felixcca at yahoo.ca <mailto:felixcca at yahoo.ca>) schrieb:
> 
>> We could do it without a new guard syntax if `do` didn't need a block statement.
>> 
>> Félix
>> 
>>> Le 5 févr. 2016 à 12:54:47, Adrian Zubarev via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> a écrit :
>>> 
>>> Hello dear Swift community,
>>> 
>>> this proposal might seem like some new syntax sugar, but it also aims to escape the 'do { }' scope from the 'do try catch‘ mechanism while making the existing error handling more powerful.
>>> 
>>> Lets assume we have some sort of network type, which can throw a ton of different errors:
>>> 
>>> struct TCPListener {
>>> init(address: String) throws { /* implement */ }
>>> 
>>> func accept() throws -> TCPConn { /* implement */ }
>>> 
>>> /* ... */
>>> }
>>> 
>>> A way of implimentation might look like this:
>>> 
>>> let listener: TCPListener
>>> do {
>>> listener = try TCPListener("some valid address")
>>> 
>>> // we could do more work here, but if we need to catch more
>>> // errors we will result in a new PYRAMIDE OF DOOM
>>> } catch {
>>> fatalError()
>>> }
>>> 
>>> At this point think about the comment inside the 'do { }' scope. Such an application might result in a new pyramide of doom as we know from optional unwrapping before 'guard else' mechanism was introduced.
>>> 
>>> let clientConn: TCPConn
>>> do {
>>> clientConn = try listener.accept() // save to call accept method
>>> } catch {
>>> fatalError()
>>> } 
>>> 
>>> As you can see this application might not need the extra 'do' scope at all, and if it does, the 'do try catch' is still there.
>>> 
>>> I propose a new error handling mechanism that mimics the solution for optional pyramide of doom, which adds a slightly better syntax and removes the unneeded/unused 'do { }' scope (as for the example from above). Not only can this mechanism guarantee the execution of a throwing function without any errors (like a true guard condition) it also can assign returned values to a new constant/variable.
>>> 
>>> Introducing the 'guard try catch' mechanism:
>>> 
>>> guard try throwingFunc() catch { 
>>> /* handle error */ 
>>> }
>>> 
>>> guard try throwingFunc() catch _ { 
>>> /* handle error */ 
>>> }
>>> 
>>> guard try throwingFunc() catch pattern { 
>>> /* handle error */ 
>>> }
>>> 
>>> guard try throwingFunc() catch pattern where condition { 
>>> /* handle error */ 
>>> }
>>> 
>>> guard let newInstance = try throwingFuncReturns() catch ... { 
>>> /* handle error */ 
>>> }
>>> 
>>> Where '...' represents the different combinations of possible patterns already showed in the first 4 examples.
>>> 
>>> We also might want the return type to be mutable.
>>> 
>>> guard var newMutableInstance = try throwingFuncReturns() catch ... { 
>>> /* handle error */ 
>>> }
>>> 
>>> This mechanism also makes the error handling more powerful, since it can catch more specific errors defined with 'where condition'.
>>> 
>>> Lets rebuild the example from above with the new mechanism:
>>> 
>>> guard let listener = try TCPListener("some valid address") catch {
>>> fatalError()
>>> }
>>> 
>>> guard let clientConn = try listener.accept() catch {
>>> fatalError()
>>> } 
>>> 
>>> One think that should be mentioned here is that the method call from the second 'guard' is safe, because a 'guard' body may not fall through.
>>> 
>>> Impact on existing codebase: None, because the mechanism is new and does not break any existing code.
>>> 
>>> I'm really curious about your opinions.
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>>> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160205/0847d533/attachment.html>


More information about the swift-evolution mailing list