<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=""><div class="">I dashed these emails off very quickly, which is something I should never do here. There problems with the “trailing catch” idea. Some of them could be made to work, with enough rules added, but it would probably have been best to just stick with my original objection to adding special-case syntactic sugar at this point in the evolution of the language.</div><div class=""><br class=""></div><div class="">The "trailing catch” would be pretty straightforward for `try?` and `try!` calls, since both handle the lack of a return value from the called function. There is currently no way to do anything with exceptions thrown from `try?` and ‘try!’, so there might be some value for these.`try` is more problematic and would require an exit or a or an exception to be thrown from the catch block. This adds more rules to ‘catch’, which argues against including it in the language. Another keyword like “intercept” for catches that would guarantee that an exception is thrown from the handling block would be a better choice for “try”, I think, but the bar for new keywords is justifiably very high.</div><div class=""><br class=""></div><div class="">In any case, the logic from all uses of a "trailing catch" can be replicated with nested do/catch blocks, so I do not think that these ideas should be considered now.</div><div class=""><br class=""></div><div class="">The “trailing catch” idea might fit with Dave DeLong’s suggestion of a few days ago, in which he wanted support for detailed diagnostics (hopefully that is a correct summary). If/when that topic ever is considered, then the "trailing catch” may have a place as part of that effort.</div><div class=""><br class=""></div><div class=""><br class=""></div><div><blockquote type="cite" class=""><div class="">On Jul 8, 2017, at 5:16 PM, Christopher Kornher via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;">Thanks for you considerate reply. My concern over the proliferation of “sugar proposals” is a general one. This proposal has more merit and general utiliity than many others. I have never used a throwing function in a guard statement that was not itself in a throwing function, but I can see that it could possibly be common in some code. Wrapping a guard statement and all the code that uses variables set in the guard in a do/catch is sub-optimal.</div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" class=""><div class="">On Jul 8, 2017, at 4:16 PM, Benjamin Spratling via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class=""><br class=""><blockquote type="cite" class="">On Jul 8, 2017, at 4:08 PM, Christopher Kornher <<a href="mailto:ckornher@me.com" class="">ckornher@me.com</a>> wrote:<br class=""><br class="">I am opposed to this proposal because it muddies up the language to support what is essentially an edge case. The standard way to exit a function early because an exception is thrown is to make the function itself throw, if it is part of a larger operation. The addition of a few lines of try/catch code is not a great burden and makes the termination of an an exception very clear.<br class=""></blockquote><br class="">I’ve read your email, but haven’t digested it fully. One thing I agree with is that most functions which call throwing functions don’t actually use a do…catch block, but instead are merely marked “throws” and the error is propagated back through the stack. Once I seriously started coding functions with errors, I realized I almost always wanted my errors to reach my view-controller or my business logic so I could present separate UI if a real error occurred, and often my error message depended on the details of the error instance.<br class=""><br class=""><blockquote type="cite" class="">`guard` statements are generally used to set variables that are needed in the body of a function. Using them to save a few lines of exception handing code is a very different use. There is no need to mix two relatively clean syntaxes for a few edge cases and increase cognitive load one more time,<span class="Apple-converted-space"> </span><br class=""></blockquote><br class=""><br class="">I disagree with your conclusion on this point.<br class="">The “guard” syntax is specifically designed to achieve early return (and placing code associated with early return at the point where it happens) and cleanly installing the returned value into the surrounding scope. So far it has been used to achieve early return only with optionals, true. But is that inherent to ‘guard’, or is it merely because that’s the only way it has been used? The guard does set variables that are needed in the body of the function, and that’s exactly why using guard with values returned from throwing functions makes so much sense, because it does exactly the same thing in a general sense. The “do”…”catch” structure is intentionally designed differently, to place the “happy path” in one place and place the returns in another place. I think with guard/else, we’re seeing developers who can handle less cognitive loading find it easier to reason about early return than grouping failures after the happy path. This proposal hopes to introduce that better language architecture to the catching of errors.<br class=""></div></div></blockquote><div class=""><br class=""></div>All catches don’t have to exit the outer scope, so using guard only handles a subset <br class=""><div class=""><br class=""></div><div class="">It think that creating the terse try/catch for simple cases has multiple advantages:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>1) I think that it addresses your desire for a simple way to use throwing functions easily in guard statements.</div><div class=""><br class=""></div><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>2) It avoids having to change the guard syntax to accomplish this</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>3) It is useful for handling simple one line try/catch constructs in less space in a way that should not seem too foreign to Swift developers.</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>4) It simplifies code that currently uses nested do/try/catch constructs. Even though this is rare, it introduces significant “rightward drift”.</div><div class=""><br class=""></div></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>5) It can used to return early from void throwing functions easily. e.g. : </div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>```</div></div><blockquote class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; margin: 0px 0px 0px 40px; border: none; padding: 0px;"><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>guard try foo( ) catch { return }</div></div></blockquote><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>```</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>Multiple void throwing functions would probably be better handled by a do/catch block, but there is no danger of needing values from these functions because there are none:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>```</div></div><blockquote class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; margin: 0px 0px 0px 40px; border: none; padding: 0px;"><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>do {</div></div><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>try fn1()</div></div><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>try fn2()</div></div><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>} catch {</div></div><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>// keep going, return or call a non-returning function, since throw is already handled by declaring a throwing enclosing function.</div></div><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>// No varibles are needed by the outer block because none are set</div></div><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>// So it is not clearly a guard-like statement</div></div><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}<span class="Apple-tab-span" style="white-space: pre;">        </span> </div></div></blockquote><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>```</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>I did not think of this before, but perhaps we could allow `do` to be replaced with `guard`, thereby allowing values to escape to the outer scope, while still ensuring an early exit:</div><div class=""><br class=""></div><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>```</div></div></div><blockquote class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; margin: 0px 0px 0px 40px; border: none; padding: 0px;"><div class=""><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>guard {</div></div></div><div class=""><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>try fn1()</div></div></div><div class=""><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>try fn2()</div></div></div><div class=""><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>let x = fn3()</div></div></div><div class=""><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>} catch {</div></div></div><div class=""><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>// Must exit</div></div></div><div class=""><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>} else {</div></div></div><div class=""><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>// Must exit</div></div></div><div class=""><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}<span class="Apple-tab-span" style="white-space: pre;">        </span> </div></div></div></blockquote><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>```</div><div class="">I am not sure that “leaky” braces are a good idea, so perhaps some other character could be used to indicate a non-scope or whatever you want to call it:</div><div class=""><br class=""></div><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>```</div></div></div></div><blockquote class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; margin: 0px 0px 0px 40px; border: none; padding: 0px;"><div class=""><div class=""><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>guard <your favorite character here></div></div></div></div><div class=""><div class=""><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>try fn1()</div></div></div></div><div class=""><div class=""><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>try fn2()</div></div></div></div><div class=""><div class=""><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>let x = fn3()</div></div></div></div><div class=""><div class=""><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span> <another favorite character here> catch {</div></div></div></div><div class=""><div class=""><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>// Must exit</div></div></div></div><div class=""><div class=""><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>} else {</div></div></div></div><div class=""><div class=""><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>// Must exit</div></div></div></div><div class=""><div class=""><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}<span class="Apple-tab-span" style="white-space: pre;">        </span> </div></div></div></div></blockquote><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class=""><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>```</div><div class="">This would make the language even harder to read, so just using braces is probably a better idea.</div></div><div class=""><br class=""></div><div class="">This would change the guard syntax slightly, but is a straightforward extrapolation of do/catch and guard, I think. Of course, this could replace the existing guard syntax entirely and its use of semicolons, if we want to go that far…</div><div class=""><br class=""></div><div class="">Allowing this syntax only if one of the expressions throws is possibly a good backward-compatible solution that would avoid redundant guard syntaxes.</div><div class=""><br class=""></div><div class="">Anyway there are lot of possibilities here. We are not forced to extend the guard statement as it exists today. The current guard statement syntax was quite controversial when it was introduced and extending it may not be the best option to do what you want.</div><div class=""><br class=""></div><div class="">- Chris</div></div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><br class=""><blockquote type="cite" class=""><div class=""><div class=""><br class="">-Ben Spratling<br class=""><br class="">_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></div></div></blockquote></div><br class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">_______________________________________________</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">swift-evolution mailing list</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><a href="mailto:swift-evolution@swift.org" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">swift-evolution@swift.org</a><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></div></blockquote></div><br class=""></body></html>