<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">I came up with an interesting idea that might make a nice enhancement to Swift’s current error handling. I’m curious to see whether others think it is worth pursuing or not.<div class=""><br class=""></div><div class="">There are two motivating examples for this. It could provide the obvious way to flow errors through code written in continuation passing style (whether asynchronous or not). It could also provide a way to abstract over common error handling code.<br class=""><div class=""><div class=""><br class=""></div><div class="">The basic idea is to allow catching functions that would be a complement to throwing functions. Catching functions would have one or more catch blocks at the top level and could also accept arguments:</div><div class=""><br class=""></div><div class="">func handler(int i: Int, str: String) catches {</div><div class=""> // i and str are in scope</div><div class="">} catch VendingMachineError.InvalidSelection {</div><div class=""> // i and str are <b class="">not </b>in scope</div><div class="">} catch VendingMachineError.OutOfStock {</div><div class=""> // i and str are <b class="">not </b>in scope</div><div class="">}</div></div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">The function could be called as normal: </div><div class="">handler(int: 1, str: “”) </div><div class=""><br class=""></div><div class="">In this case the body would be executed.</div><div class=""><br class=""></div><div class="">The function could also be called with a “catch” clause: </div><div class="">handler(catch VendingMachineError.InvalidSelection)</div><div class=""><br class=""></div><div class="">In this case the top level catch clauses would be evaluated as if they part of a do-catch statement in which an error was thrown.</div></div><div class=""><br class=""></div><div class="">Note that there is no colon after the `catch` in the function call. This would avoid conflicting with a potential argument named catch and would also call attention to the fact that it is not a normal argument. I don’t think <span class="Apple-tab-span" style="white-space: pre;">        </span>`throw` would be appropriate here as that could be ambiguous if the function containing the call to `handler` was a throwing function and also because an error would not be thrown up the stack, but rather caught directly by `handler`.</div><div class=""><br class=""></div><div class="">It may be worthwhile to consider requiring a catching function to handle all errors if it wishes to return a value so that it is able to return a value when catching an error no matter what the error is. </div><div class=""><br class=""></div><div class="">Alternatively, (and maybe more interesting) since the compiler knows at the call site whether the function was provided regular arguments or an error to catch these two cases could be handled independently, with the body returning a value and the result of a “catching” call returning a value indicating whether the error was handled or not (or something similar).</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">Here is how this would look when it is applied to the motivating examples. </div><div class=""><br class=""></div><div class="">First is a cps example using a catching closure.</div><div class=""><br class=""></div><div class="">// @exhaustive requires the catching function to catch <b class="">all</b> errors</div><div class="">func cps(then: Int -> () @exhaustive catches) {</div><div class=""> if (checkSomeState) {</div><div class=""> then(42)</div><div class=""> } else {</div><div class=""> then(catch VendingMachineError.InvalidSelection)</div><div class=""> }</div><div class="">}</div><div class=""><br class=""></div><div class="">cps() { i: Int in</div><div class=""> // do some work using i</div><div class=""><div class="">} catch VendingMachineError.InvalidSelection {</div><div class=""> // handle the error, i is not in scope</div><div class="">} catch VendingMachineError.OutOfStock {</div></div><div class=""> // handle the error, i is not in scope</div><div class="">} catch {</div><div class=""> // handle all other errors</div><div class="">}</div><div class=""><br class=""></div><div class="">Second is an example showing how this could be used to abstract over error handling logic:</div><div class=""><br class=""></div><div class="">func handler() catches {</div><div class=""><div class="">catch VendingMachineError.InvalidSelection {</div><div class=""> // some common code handling InvalidSelection</div><div class="">catch VendingMachineError.OutOfStock {</div></div><div class=""> // some common code handling OutOfStock</div><div class="">// handle some other cases as well</div><div class="">}</div><div class=""><br class=""></div><div class="">func doSomething() {</div><div class=""><br class=""></div><div class=""> do {</div><div class=""><br class=""></div><div class=""> try someThrowingFunction()</div><div class=""><br class=""></div><div class=""> } catch handler { // compiler inserts call: handler(catch errorThatWasThrown)</div><div class=""><br class=""></div><div class=""> // not sure if a body would make sense here</div><div class=""> // if it does it would only be executed when handler actually handled the error</div><div class=""><br class=""></div><div class=""> // we only proceed to the next case if handler <b class="">did not</b> handle the error</div><div class=""> } catch VendingMachineError.InsufficientFunds(let coinsNeeded) {</div><div class=""><br class=""></div><div class=""> // we can provide arguments to the error handling logic by calling a function that returns a catching closure</div><div class=""> } catch someFunctionReturningAClosureThatCatches(arg: someValueDeterminingHowToHandleErrors)</div><div class=""> }</div><div class=""><br class=""></div><div class="">}</div></body></html>