<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><blockquote type="cite" class=""><div class="">On Dec 7, 2015, at 8:30 PM, Liam Butler-Lawrence via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><div class=""><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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-stroke-width: 0px;"><div class="">Hi Kame,</div><div class=""><br class=""></div><div class="">Thanks for the work you put into this! I’ll give my thoughts on each proposed syntax:</div><div class=""><br class=""></div><div class=""><blockquote type="cite" class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(207, 135, 36);">// First syntax:</div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(53, 86, 138);"><span class="">&nbsp; &nbsp;&nbsp;</span>guard<span class="">&nbsp;</span>let</div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(207, 135, 36);"><span class="">&nbsp; &nbsp; &nbsp; &nbsp; bar = bar,&nbsp;&nbsp;</span>// Has to be non-nil</div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(207, 135, 36);"><span class="">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</span><span class="" style="color: rgb(53, 86, 138);">try</span><span class="">&nbsp;foo(</span><span class="" style="color: rgb(232, 35, 0);">"Hello"</span><span class="">), &nbsp;&nbsp;</span>// Has to not throw an error</div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;">&nbsp; &nbsp; &nbsp; &nbsp; x =&nbsp;<span class="" style="color: rgb(53, 86, 138);">try</span>&nbsp;qux()</div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span class="" style="color: rgb(53, 86, 138);">where</span>&nbsp;bar &gt;&nbsp;<span class="" style="color: rgb(53, 86, 138);">10</span></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(207, 135, 36);"><span class="">&nbsp; &nbsp;&nbsp;</span><span class="" style="color: rgb(53, 86, 138);">else</span><span class="">&nbsp;{&nbsp; &nbsp;&nbsp;</span>// Has to not throw an error</div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(207, 135, 36);"><span class="">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</span><span class="" style="color: rgb(53, 86, 138);">return</span><span class="">&nbsp;&nbsp;</span>// Bar or baz was nil</div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;">&nbsp; &nbsp; }&nbsp;<span class="" style="color: rgb(53, 86, 138);">catch</span>&nbsp;Error.Some {</div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(207, 135, 36);"><span class="">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</span><span class="" style="color: rgb(53, 86, 138);">return</span><span class="">&nbsp;&nbsp;</span>// Some Error occured</div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;">&nbsp; &nbsp; }&nbsp;<span class="" style="color: rgb(53, 86, 138);">catch</span>&nbsp;{</div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(207, 135, 36);"><span class="">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</span><span class="" style="color: rgb(53, 86, 138);">return</span><span class="">&nbsp;&nbsp;</span>// Another Error occured</div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;">&nbsp; &nbsp; }</div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;">&nbsp;&nbsp; &nbsp;<br class="webkit-block-placeholder"></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(207, 135, 36);"><span class="">&nbsp; &nbsp;&nbsp;</span>// `else` has to be there for optional, `catch` for errors</div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;">&nbsp; &nbsp;&nbsp;<span class="" style="color: rgb(53, 86, 138);">guard</span>&nbsp;<span class="" style="color: rgb(53, 86, 138);">try</span>&nbsp;foo(<span class="" style="color: rgb(232, 35, 0);">"Hello"</span>),&nbsp;<span class="" style="color: rgb(53, 86, 138);">let</span>&nbsp;x =&nbsp;<span class="" style="color: rgb(53, 86, 138);">try</span>&nbsp;qux()&nbsp;<span class="" style="color: rgb(53, 86, 138);">where</span>&nbsp;x &lt;&nbsp;<span class="" style="color: rgb(53, 86, 138);">10</span>&nbsp;<span class="" style="color: rgb(53, 86, 138);">catch</span>&nbsp;Error.Some {</div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span class="" style="color: rgb(53, 86, 138);">return</span></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;">&nbsp; &nbsp; }&nbsp;<span class="" style="color: rgb(53, 86, 138);">catch</span>&nbsp;{</div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span class="" style="color: rgb(53, 86, 138);">return</span></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;">&nbsp; &nbsp; }</div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;">&nbsp;&nbsp; &nbsp;<br class="webkit-block-placeholder"></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(207, 135, 36);"><span class="">&nbsp; &nbsp;&nbsp;</span>// Results can be ignored; catch can be on new line</div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(53, 86, 138);"><span class="">&nbsp; &nbsp;&nbsp;</span>guard<span class="">&nbsp;</span>let</div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span class="" style="color: rgb(53, 86, 138);">_</span>&nbsp;=&nbsp;<span class="" style="color: rgb(53, 86, 138);">try</span>&nbsp;foo(<span class="" style="color: rgb(232, 35, 0);">"Hello"</span>),</div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span class="" style="color: rgb(53, 86, 138);">_</span>&nbsp;=&nbsp;<span class="" style="color: rgb(53, 86, 138);">try</span>&nbsp;qux()</div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(207, 135, 36);"><span class="">&nbsp; &nbsp;&nbsp;</span><span class="" style="color: rgb(53, 86, 138);">catch</span><span class="">&nbsp;Error.Some {&nbsp;&nbsp;</span>// Not 100% beautiful</div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span class="" style="color: rgb(53, 86, 138);">return</span></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;">&nbsp; &nbsp; }&nbsp;<span class="" style="color: rgb(53, 86, 138);">catch</span>&nbsp;{</div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span class="" style="color: rgb(53, 86, 138);">return</span></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;">&nbsp; &nbsp; }</div></div></div></blockquote></div><div class=""><br class=""></div><div class="">This is comprehensive and seems (to me, anyway!) like it could definitely work. My only concern is that the similar-but-different syntaxes for the different optional/<span class="" style="color: rgb(53, 86, 138); font-family: Menlo; font-size: 11px;">try</span>&nbsp;combinations could be a bit confusing. I see the following three unique syntaxes in your proposal:</div><div class=""><br class=""></div><div class=""><blockquote type="cite" class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(53, 86, 138);"><span class="">&nbsp; &nbsp;&nbsp;</span>guard<span class="">&nbsp;</span>let x = y, try z(a) else { } catch E { }... catch { }</div></div></div></blockquote><blockquote type="cite" class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(53, 86, 138);"><span class="">&nbsp; &nbsp;&nbsp;</span>guard<span class="">&nbsp;let x =&nbsp;</span>try z(a) else { } catch E { }... catch { }</div></div></div></blockquote><div class=""><blockquote type="cite" class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(53, 86, 138);"><span class="">&nbsp; &nbsp;&nbsp;</span>guard<span class="">&nbsp;</span>try z(a) catch E { }... catch { }</div></div></div></blockquote><br class=""><blockquote type="cite" class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""></div></div></blockquote></div></div><div class="">That’s not even considering&nbsp;<span class="" style="color: rgb(53, 86, 138); font-family: Menlo; font-size: 11px;">where</span>&nbsp;conditions, or chaining more than a single optional and&nbsp;<span class="" style="color: rgb(53, 86, 138); font-family: Menlo; font-size: 11px;">try</span>&nbsp;together in a single&nbsp;<span class="" style="color: rgb(53, 86, 138); font-family: Menlo; font-size: 11px;">guard</span>&nbsp;expression.&nbsp;</div></div></div></blockquote><div><br class=""></div>This proposal packs an awful lot into a single “guard” statement, but that might be okay; it’s just something that I personally am not totally comfortable with.</div><div><br class=""></div><div>The larger problem that I see is that this changes the semantic behavior of “guard” quite a bit. &nbsp;Normally, in something like:</div><div><br class=""></div><div>&nbsp; guard let x = foo(),</div><div>&nbsp; &nbsp; &nbsp; &nbsp; bar()</div><div>&nbsp; &nbsp; else { … }</div><div><br class=""></div><div>these clauses are both expected to be conditional: that is, foo() is expected to return an optional type, bar() is expected to return a Bool, etc. &nbsp;The guard protects against the exceptional conditions. &nbsp;But this isn’t really what you want, because the exceptional condition you’re looking to guard against is whether the expression threw. &nbsp;Thus, in the corresponding example:</div><div><br class=""></div><div>&nbsp; guard let x = try foo(),</div><div>&nbsp; &nbsp; &nbsp; &nbsp; try bar()</div><div>&nbsp; &nbsp; catch { … }</div><div>&nbsp;&nbsp;</div><div>it should at the very least be acceptable for foo() to return a non-optional type, and if it doesn’t, it’s debatable whether you really want to unwrap it; and similarly, it might be reasonable for bar() to return Void, e.g.:</div><div><br class=""></div><div>&nbsp; guard try registerUser()</div><div>&nbsp; &nbsp; catch { … }</div><div><br class=""></div><div>Part of this is just the original sin that “if let” and “guard let” aren't very composable. &nbsp;For example, you run into a very similar problem with normal “guard” just by trying to bind a non-optional value between two other conditions, e.g.:</div><div>&nbsp; guard let resolver = factory.currentResolver,</div><div>&nbsp; &nbsp; &nbsp; &nbsp; let numResolved = resolver.resolvedEntityCount,</div><div>&nbsp; &nbsp; &nbsp; &nbsp; numResolved &lt; maxResolutionCount</div><div>&nbsp; &nbsp; else { … }</div><div><br class=""></div><div>However, this new pattern for guard really exacerbates the problem, both because it’s so common to have functions with non-optional results that throw errors, and because even when the function has an optional result, it’s ambiguous whether you really want to simultaneously unwrap it. &nbsp;In other words, there’s too much magic in this syntax, and it seems to be colliding.</div><div><br class=""></div><div>One possible solution is to say that “guard let" only unwraps results if there’s an else clause. &nbsp;(What happens with “guard try foo()” in this case?) &nbsp;But that means that adding and removing an else clause has very subtle and hard-to-explain semantic effects on the semantics of “guard”. &nbsp;I’m tempted to say that we just shouldn’t allow the combination of an else clause and catch clauses, but that’s just begging for people to ask for the combination, at which point we’ll have codified two incompatible models for the statement.</div><div><br class=""></div><div>John.</div></body></html>