<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 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.</div><div class=""><br class=""></div><div 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, </div><div class=""><br class=""></div><div class="">If we really want a more compact try/catch syntax, we should not use (abuse?) the `guard` statement, but instead allow a training catch which reads similarly to a trailing closure:</div><div class=""><br class=""></div><div class="">```</div><div class="">let x = try aFunction() catch ( let e: Error ) {</div><div class=""> <span class="Apple-tab-span" style="white-space:pre">        </span>… </div><div class="">} </div><div class=""><br class=""></div><div class="">```</div><div class=""><br class=""></div><div class=""><div class="">This might be confused with trailing closures, but since most editors will highlight the `catch`, the meaning should be pretty clear.</div></div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">Using this in a `guard` would look like: </div><div class=""><br class=""></div><div class="">```</div><div class="">guard let x = try aFunction() catch ( let e: Error ) { … // must exit };</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>let y=y;</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>let z=x else {</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>...</div><div class="">}</div><div class="">```</div><div class="">Multiple throwing statements in the guard could be handled like:</div><div class=""><br class=""></div><div class=""><div class="">```</div><div class="">guard let x = try aFunction();</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>let xx = try aFunction2() catch ( let e: Error ) { … // must exit };</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let y=y;</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let z=x else {</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>...</div><div class="">}</div><div class="">```</div></div><div class="">but this creeps toward the original proposal and I do not think that the added complexity is worth the trouble. I prefer the simpler syntax for the rare cases where is more than one throwing statement within the guard:</div><div class=""><br class=""></div><div class=""><div class=""><div class="">```</div><div class="">guard let x = try aFunction() catch ( let e: Error ) { … // must exit };</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let xx = try aFunction2() catch ( let e: Error ) { … // must exit };</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let y=y;</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let z=x else {</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>...</div><div class="">}</div><div class="">```</div></div></div><div class=""><br class=""></div><div class="">This addition, I believe, adds much more power to the language and retains the simplicity of the “guard” statement.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">It helps clean-up code like:</div><div class=""><br class=""></div><div class=""><div class="">```</div><div class="">func attemptComplexOperation() throws {</div><span class="Apple-tab-span" style="white-space: pre;">        </span>do {<br class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>let x = try functionA()<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>} catch ( let e: Error ) {<br class=""><blockquote style="margin: 0px 0px 0px 40px; border: none; padding: 0px;" class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>Log.error( “could not do A: \(String(describing:e)” )<br class="">throw e<br class="">}<br class=""><div class=""><br class=""></div></blockquote><span class="Apple-tab-span" style="white-space: pre;">        </span>do {<br class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>let y = try functionB()<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>} catch ( let e: Error ) {<br class=""><blockquote style="margin: 0px 0px 0px 40px; border: none; padding: 0px;" class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>Log.error( “could not do B: \(String(describing:e)” )<br class="">throw e<br class="">}<br class=""><blockquote style="margin: 0px 0px 0px 40px; border: none; padding: 0px;" class=""><div class="">}</div></blockquote></blockquote><div class="">```</div><div class=""><br class=""></div><div class="">to:</div><div class=""><br class=""></div><div class="">```</div><div class="">func attemptComplexOperation() throws {</div><blockquote style="margin: 0px 0px 0px 40px; border: none; padding: 0px;" class=""><div class="">let x = try functionA() catch ( let e: Error ) {</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>Log.error( “could not do A: \(String(describing:e)” )</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>throw e</div><div class="">}</div><div class=""><br class=""></div><div class="">let Y = try functionB() catch ( let e: Error ) {</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>Log.error( “could not do B: \(String(describing:e)” )</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>throw e</div><div class="">}</div></blockquote><div class="">}</div><div class="">```</div><div class=""><br class=""></div><div class="">This this is error-prone because exception rethrowing could be omitted and the code would still compile. Perhaps another keyword to act upon an exception, but not consume it would be useful (I am sure that this idea will be popular :) )</div><div class=""><div class=""><br class=""></div><div class="">```</div><div class="">func attemptComplexOperation() throws {</div><blockquote style="margin: 0px 0px 0px 40px; border: none; padding: 0px;" class=""><div class="">let x = try functionA() intercept ( let e: Error ) {</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>Log.error( “could not do A: \(String(describing:e)” )</div><div class="">}</div><div class=""><br class=""></div><div class="">let Y = try functionB() intercept ( let e: Error ) {</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>Log.error( “could not do B: \(String(describing:e)” )</div><div class="">}</div></blockquote><div class="">}</div><div class="">```</div><div class=""><br class=""></div></div></div><div class="">I hope that the themes for Swift 5 comes soon from the core team, so we can slow down the discussions of the 'syntactic sugar proposal of the week'. I fear that Swift will become a much more complex and difficult to read language if we keep adding sugar to handle special cases. I hope that it doesn’t become too difficult to understand through all the special-case sugar coating. Perhaps more importantly, there are important features awaiting implementation that are needed by members of the community that will be delayed and possibly complicated by the addition of syntactic sugar.</div><div class=""><br class=""></div><div class="">If the decision is to accept the original proposal, then I vote for #1 below. Note that exceptions could be handled within the else clause by changing the order. I don’t think that this would be a good idea, however, as it makes the statement even harder to understand:</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">Please, not this:</div><div class="">```</div><div class=""><div dir="auto" class=""><div class="">guard let result:Result = try doSomething()</div><div class="">else { try cleanup() }</div><div class="">catch { ...}</div><div class="">```</div></div></div><div class=""><br class=""></div><br class=""><div><blockquote type="cite" class=""><div class="">On Jul 8, 2017, at 12:15 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=""><meta http-equiv="content-type" content="text/html; charset=utf-8" class=""><div dir="auto" class=""><div class=""><br class=""></div><blockquote type="cite" class=""><div class=""><font face="Menlo" class=""><span style="font-size: 11px;" class="">func doSomething() throws → Result? { … }</span></font></div><div class=""><br class=""></div><div class="">How would you handle both the catch and the let binding of the result?</div></blockquote><br class=""><div class="">I agree this proposal needs to define the behavior, since returning an optional from a throwing function is valid.</div><div class=""><br class=""></div><div class="">I see a few options:</div><div class=""><br class=""></div><div class="">1) find a way to generally incorporate optional binding and error binding into the same guard clause.</div><div class="">Could it be as simple as </div><div class="">guard let result:Result = try doSomething()</div><div class="">catch { ...}</div><div class="">else { ... }</div><div class="">?</div><div class=""><br class=""></div><div class=""> 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.</div><div class=""><br class=""></div><div class="">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. <span style="background-color: rgba(255, 255, 255, 0);" class="">This makes it impossible for the developer to code and build code which accidentally does something he doesn't expect.</span></div><div class=""><br class=""></div><div class="">3) bind the optional value</div><div class=""><br class=""></div><div class="">Perhaps, when guard/catch-ing, an optional value is perfectly legal.</div><div class=""><br class=""></div><div class="">guard let result:Result? = try doSomething() catch ...</div><div class="">This is essentially how guard works with a try?today.</div><div class="">guard let result:Result? = try? doSomething() ...</div><div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""> - Ben Spratling </div></div>_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></blockquote></div><br class=""></body></html>