<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On 16 Nov 2016, at 11:06, Nick Keets 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 dir="ltr" class=""><div class="">Hello all, I'm interested in a pattern to return failure, together with an error</div><div class="">to explain why. I think that the "guard let x = x" discussion touched on the issue,</div><div class="">but didn't really go in that direction.</div><div class=""><br class=""></div><div class="">Right now, optional and boolean results work nicely with guards, but you only get</div><div class="">sucess/failure back. For example:</div><div class=""><br class=""></div><div class="">func foo() -> Int?</div><div class="">func bar() -> Bool</div><div class="">func baz(Int) -> Int?</div><div class=""><br class=""></div><div class="">guard</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">        </span>let a = foo(),</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">        </span>bar(),</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">        </span>let b = baz(a)</div><div class="">else {</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">        </span>// No information about what failed here</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">        </span>print("Something failed")</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">        </span>return</div><div class="">}</div><div class=""><br class=""></div><div class="">I see a lot of enum Result solutions being proposed, but they have the fundamental</div><div class="">problem of not having access to the error inside guards. For example:</div><div class=""><br class=""></div><div class="">enum Result<T> { case sucess(T), error(String) }</div><div class=""><br class=""></div><div class="">func foo() -> Result<Int></div><div class=""><br class=""></div><div class="">guard case let .success(value) = foo() else {</div><div class=""> // Result is .error but we have no access to the error message here</div><div class=""> return</div><div class="">}</div><div class=""><br class=""></div><div class="">I think a solution to this problem could be to allow "guard let try" statements</div><div class="">that make the error available inside the else statement. So you could write:</div><div class=""><br class=""></div><div class="">func foo() throws -> Int</div><div class="">func bar() -> Bool</div><div class="">func baz(Int) throws -> Int</div><div class=""><br class=""></div><div class="">guard</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">        </span>let a = try foo(),</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">        </span>bar(),</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">        </span>let b = try baz(a)</div><div class="">else {</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">        </span>// `error` is available here like in a catch block</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">        </span>print("Error: \(error.localizedDescription)")</div><div class=""><span class="gmail-Apple-tab-span" style="white-space:pre">        </span>return</div><div class="">}</div><div class=""><br class=""></div><div class="">A potential weirdness of this solution is that it appears indistinguishable from</div><div class="">"guard let try?" (already available) if you are not interested in the error.</div><div class=""><br class=""></div><div class="">Thoughts?</div></div></div></blockquote></div><br class=""><div class="">I think it comes to a point where you may be expecting too much of guard, when this is really what a switch or try/catch is for.</div><div class=""><br class=""></div><div class="">One of the purposes of switch is exhaustive handling for enums, so that's the best way to handle them if you're interested in more than one case. Whereas try/catch is exactly what you want if you want to, well, catch an error.</div><div class=""><br class=""></div><div class="">However, I wouldn't mind if maybe we could just have an optional catch on guard statements, like so:</div><div class=""><br class=""></div><div class=""><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>guard let a = try foo(), baz(), let b = try baz(a) </font></div><div class=""><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space:pre">                </span>else { return; } // baz() returned false, or foo() or baz() returned nil</font></div><div class=""><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space:pre">                </span>catch(error) { print("Error: \(error.localizedDescription)"); return } // foo() or baz() threw an exception</font></div><div class=""><br class=""></div><div class="">This would still have the same requirements as a guard's else statement (must change flow with break, return, throw etc.) but is only triggered in the exception case. If your guard condition can *only* fail as a result of an exception then you can omit the else. For example, if you skip the call to bar(), and foo() and baz(a) can't return nil then the following would be valid:</div><div class=""><br class=""></div><div class=""><font face="Monaco" class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>guard let a = try foo(), let b = baz(a) </font><span style="font-family: Monaco;" class="">catch(error) { print("Error: \(error.localizedDescription)"); return }</span></div><div class=""><br class=""></div><div class="">The main benefit here being that you get the same kind of in-scope a and b variables, unlike a try/catch block where they are limited to their own scope only (or you have to declare them outside which is messy).</div><div class=""><br class=""></div><div class="">I don't see how the enum case could be usefully simplified though, as you'd need to have pattern matching of some kind to define the error condition you expect, in which case you might as well just use a switch anyway, whereas a guard/catch at least eliminates an annoyance of try/catch when dealing with something that only fails initially.</div></body></html>