<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="">That seems like a straight-forward way of plugging that particular hole in the ”less-than-normal” feature set of Swift.<div class="">I do, however, think that ??? Is not a great choice, because it doesn’t indicate the error handling at all.</div><div class="">Considering that the traditional ?? means “unwrap optional or use the other value’, I’d go for something along the lines of ?throw that means “unwrap optional or throw error”.</div><div class=""><div class=""><br class=""></div><div class=""><font face="Menlo" class="">func foo() throws -> String {</font></div><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>return bar ?throw EmbarrassingError.oops</font></div><div class=""><font face="Menlo" class="">}</font></div><div class=""><br class=""></div><div class="">But there are other holes in completeness of Swift’s features that are closely related to this.</div><div class=""><br class=""><div class="">I opened a discussion a while back regarding something similar, but that discussion got abandoned without a conclusion.</div><div class="">In a nutshell, I proposed making `throws` and `inout` less magical by promoting them to proper declaration specifiers.</div><div class="">Currently, something like </div><div class=""><span style="font-family: Menlo;" class=""><br class=""></span></div><div class=""><span style="font-family: Menlo;" class="">var foo: inout String = &bar</span></div><div class=""><br class=""></div><div class="">can be exactly replicated in the following way:</div><div class=""><br class=""></div><div class=""><font face="Menlo" class="">var foo: String {</font></div><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>get {</font></div><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">                </span>return bar</font></div><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>}</font></div><div class=""><span class="Apple-tab-span" style="white-space:pre"><font face="Menlo" class="">        </font></span></div><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>set {</font></div><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">                </span>bar = newValue</font></div><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>}</font></div><div class=""><font face="Menlo" class="">}</font></div><div class=""><br class=""></div><div class="">So the would be just some minor syntax sugar for logical completeness and convenience.</div><div class="">Further helping the logical completeness of `inout` would be allowing functions to have a `get` and `set` accessors just like subscripts. This would allow implementing a `set` accessor of the function, essentially making it an `inout` function with all the usual perks like the prefix ampersand operator.</div><div class=""><br class=""><div class="">The `throws` could get the same treatment by first allowing property accessors to be marked as `throws`:</div><div class=""><br class=""></div><div class=""><font face="Menlo" class="">var foo: String throws {</font></div><div class=""><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>return try throwingFunction()</font></div><div class=""><font face="Menlo" class="">}</font></div><div class=""><span style="font-family: Menlo;" class=""><br class=""></span></div><div class=""><span style="font-family: Menlo;" class="">print(try foo)</span></div><div class=""><span style="font-family: Menlo;" class=""><br class=""></span></div><div class="">Then getting a syntax sugar just like `inout`:</div><div class=""><br class=""></div><div class=""><font face="Menlo" class="">var foo: String throws = throwingFunction() // notice the lack of `try`, due to the fact that the error from `throwingFunction()` is not thrown into the current scope.</font></div><div class=""><br class=""></div><div class="">In cases where the getter and setter of the variable can have different thowing capabilities, the trick used by access level indicators could be used:</div><div class=""><br class=""></div><div class=""><font face="Menlo" class="">var foo: String throws(set)</font></div><div class=""><br class=""></div><div class="">or</div><div class=""><br class=""></div><div class=""><font face="Menlo" class="">var foo: String throws(get)</font></div><div class=""><br class=""></div><div class="">What do you think?</div><div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Jul 30, 2017, at 9:37 PM, Erica Sadun <<a href="mailto:erica@ericasadun.com" class="">erica@ericasadun.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">From 2016:<div class=""><br class=""></div><div class="">See: <a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160404/014272.html" class="">https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160404/014272.html</a></div><div class="">and <a href="https://gist.github.com/erica/5a26d523f3d6ffb74e34d179740596f7" class="">https://gist.github.com/erica/5a26d523f3d6ffb74e34d179740596f7</a></div><div class=""><br class=""></div><div class="">-- E</div><div class=""><br class=""><div class=""><div class=""><blockquote type="cite" class=""><div class="">On Jul 30, 2017, at 12:30 PM, Gor Gyolchanyan 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="">I like the general direction where this is going, but I haven’t settled on an opinion regarding its appearance yet.<br class="">I’ve argued before that the gap between optionals and errors should be closed by making it easy to swift from optionals to non-optionals with throwing.<br class="">The “unwrap-or-die” idea discussed earlier is very similar to this.<br class=""><br class="">In the end, I think all optional, throwing and fatalError-related proposals have to be united and carefully considered as an overarching proposal to extend and complete Swift’s representation of “less-than-normal” situations.<br class=""><br class=""><blockquote type="cite" class="">On Jul 30, 2017, at 9:25 PM, Robert Bennett via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:<br class=""><br class="">This idea was sparked by conversation in another thread about a more concise way to write the following:<br class=""><br class="">guard let x1 = f1(), let x2 = f2(), ... else { ... }<br class="">doSomething(with: x1)<br class="">doSomething(with: x2)<br class="">...<br class=""><br class="">It was suggested to write a function that throws when an optional is nil, and then wrapping the calls to f1, f2, ... in that function, and then wrapping *those* in a do-catch block. This would both exit early in case one value was nil, and also use the values as soon as they’re available instead of needing to assign them to a temp variable first and using the temp variable.<br class=""><br class="">Instead of a throwing unwrap function, I am proposing a throwing unwrap operator. This operator would work like !, but instead of a fatal error when the value is nil, it would throw.<br class=""><br class="">struct UnwrapError: Error {}<br class="">postfix operator ^?<br class="">extension Optional {<br class=""> static postfix func ^?(optional: Optional) throws -> Wrapped {<br class=""> guard let wrapped = optional else {<br class=""> throw UnwrapError()<br class=""> }<br class=""> return wrapped<br class=""> }<br class="">}<br class=""><br class="">In addition, to round this out, I think it would be helpful to be able to throw arbitrary errors, as a nil value may carry meaning that should be propagated to the rest of the program. Thus there could be a throwing nil coalescing operator, which returns the unwrapped value if non-nil, or throws the specified error if nil.<br class=""><br class="">infix operator ^??<br class="">extension Optional {<br class=""> static func ^??(lhs: Optional, rhs: Error) throws -> Wrapped {<br class=""> guard let wrapped = lhs else {<br class=""> throw rhs<br class=""> }<br class=""> return wrapped<br class=""> }<br class="">}<br class=""><br class="">Thoughts? I think these would be helpful additions to allow doing something with Optionals while simultaneously exiting early in the case of a nil value — putting the unwrapping, the use, and the exiting early all on one line. <br class=""><br class="">Hopefully this doesn’t distract from the other important conversations happening on the mailing list!<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=""></blockquote><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=""></div></div></div></div></blockquote></div><br class=""></div></div></div></div></body></html>