<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="">Yes of course you can do these things. And you could use a Result type for error handling before Swift 2. The problem is that these are ad-hoc approaches and everyone will do it slightly differently.<div class=""><br class=""></div><div class="">Error handling is important enough to justify a language feature that aids correctness and establishes a common practice. This idea may or not be the right solution. Either way I do believe Swift will be better off with a language level solution.<div class=""><br class=""></div><div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Dec 17, 2015, at 12:13 AM, Thorsten Seitz <<a href="mailto:tseitz42@icloud.com" class="">tseitz42@icloud.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="content-type" content="text/html; charset=utf-8" class=""><div dir="auto" class=""><div class=""></div><div class="">What about just writing the following (see below)? To enable the same behaviour we would have to add non-local return which would be nice for other reasons. </div><div class=""><br class=""></div><div class="">func handler<T>(block: () -> T) rethrows {</div><div class=""> do {</div><div class=""> let result = try block()</div><div class=""> return result</div><div class=""> } catch <span style="background-color: rgba(255, 255, 255, 0);" class="">VendingMachineError .InvalidSelection {</span></div><div class=""><div class=""><div class=""><font class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""> // some common code handling InvalidSelection</span></font></div><div class=""><font class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""> } catch VendingMachineError.OutOfStock {</span></font></div></div><div class=""><font class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""> // some common code handling OutOfStock</span></font></div><div class=""><font class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""> // handle some other cases as well</span></font></div><div class=""><font class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""> }</span></font></div><div class=""><font class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">}</span></font></div><div class=""><font class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></font></div><div class=""><font class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">func doSomething() {</span></font></div></div><div class=""><font class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""> do {</span></font></div><div class=""><div class=""> handler {</div></div><div class=""> <span style="background-color: rgba(255, 255, 255, 0);" class="">try someThrowingFunction()</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""> }</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""> } catch VendingMachineError.InsufficientFunds(let coinsNeeded) {</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""> // special case handled here</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""> }</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">}</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">For covering your third case using a handler function with an argument, you could add an argument to the func handler.</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">For chaining handler functions you could introduce an operator for composing handler functions.</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">-Thorsten</span></div><div class=""><br class="">Am 17.12.2015 um 06:27 schrieb Matthew Johnson via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>>:<br class=""><br class=""></div><blockquote type="cite" class=""><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" 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>
<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=1MXK54sosN3xru3iYcLt0oBZ2w20i49gyogXctgrspfWY6mqLa1srJbQDaClinHCNJbXK3s1A1qp5b7ZtO0ciz9XEgdXA5zgDqMMkBtZz4NfQucVM9fanFqEcPy-2FQT3R4T0eYeuHmKhSGK8P1rg-2BaIBzdXBWu3FB6enbEKRGo8xYRV1kDG-2FYSt4jc-2BHD1vK7J7V-2FJwnuGavVS2wmPquz6Fe3jWts32UwtucmH2lZ-2FFQ-3D" alt="" width="1" height="1" border="0" style="height:1px !important;width:1px !important;border-width:0 !important;margin-top:0 !important;margin-bottom:0 !important;margin-right:0 !important;margin-left:0 !important;padding-top:0 !important;padding-bottom:0 !important;padding-right:0 !important;padding-left:0 !important;" class="">
</div></blockquote><blockquote type="cite" class=""><div class=""><span class="">_______________________________________________</span><br class=""><span class="">swift-evolution mailing list</span><br class=""><span class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a></span><br class=""><span class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br class=""></div></blockquote></div></div></blockquote></div><br class=""></div></div></body></html>