<html><body><div>You are certainly right.<br></div><div><br data-mce-bogus="1"></div><div>I only wonder whether you really want to repeat Error() all over, possibly with `aString` etc. as argument.<br data-mce-bogus="1"></div><div>If not extracting the logic of parsing + throwing into a function or method (e.g. `toInt`) which throws the correct error for your domain, possibly enriched with some arguments, still makes more sense than using `???`.<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><div>-Thorsten</div><div><br data-mce-bogus="1"></div><div><br>Am 07. April 2016 um 15:23 schrieb Yuta Koshizawa <koher@koherent.org>:<br><br><div><blockquote type="cite"><div class="msg-quote"><div class="_stretch"><span class="body-text-content">Of course we can implement a library with `throws` by changing those<br>properties to methods. However we can think about similar cases.<br><br>```<br>do {<br> let foo: Foo = try foo(<br> a: Int(aString) ??? Error(),<br> b: Int(bString) ??? Error(),<br> c: Int(cString) ??? Error()<br> )<br>} catch _ {<br> // Error handling<br>}<br>```<br><br>`Dictionary` also returns optionals. We have already had various<br>functions/methods which returns optionals.<br><br>-- Yuta<br><br><br>2016-04-07 21:34 GMT+09:00 Thorsten Seitz via swift-evolution<br><swift-evolution@swift.org>:<br><blockquote type="cite" class="quoted-plain-text">Why not have throwing variants of the `string` and `int` methods (in</blockquote><blockquote type="cite" class="quoted-plain-text">addition to those returning an optional)?</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">Then you could simply write:</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">```</blockquote><blockquote type="cite" class="quoted-plain-text">// Decodes a JSON with SwiftyJSON</blockquote><blockquote type="cite" class="quoted-plain-text">do {</blockquote><blockquote type="cite" class="quoted-plain-text">let person: Person = try Person(</blockquote><blockquote type="cite" class="quoted-plain-text">firstName: json["firstName"].string,</blockquote><blockquote type="cite" class="quoted-plain-text">lastName: json["lastName"].string,</blockquote><blockquote type="cite" class="quoted-plain-text">age: json["age"].int)</blockquote><blockquote type="cite" class="quoted-plain-text">} catch _ {</blockquote><blockquote type="cite" class="quoted-plain-text">// Error handling</blockquote><blockquote type="cite" class="quoted-plain-text">}</blockquote><blockquote type="cite" class="quoted-plain-text">```</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">-Thorsten</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">Am 07. April 2016 um 14:01 schrieb Yuta Koshizawa via swift-evolution</blockquote><blockquote type="cite" class="quoted-plain-text"><swift-evolution@swift.org>:</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">I'd like to see some real-world examples of this before we did anything with</blockquote><blockquote type="cite" class="quoted-plain-text">it.</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">The following is my real-world example.</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">```</blockquote><blockquote type="cite" class="quoted-plain-text">// Decodes a JSON with SwiftyJSON</blockquote><blockquote type="cite" class="quoted-plain-text">do {</blockquote><blockquote type="cite" class="quoted-plain-text">let person: Person = try Person(</blockquote><blockquote type="cite" class="quoted-plain-text">firstName: json["firstName"].string ??? Error(),</blockquote><blockquote type="cite" class="quoted-plain-text">lastName: json["lastName"].string ??? Error(),</blockquote><blockquote type="cite" class="quoted-plain-text">age: json["age"].int ??? Error()</blockquote><blockquote type="cite" class="quoted-plain-text">)</blockquote><blockquote type="cite" class="quoted-plain-text">} catch _ {</blockquote><blockquote type="cite" class="quoted-plain-text">// Error handling</blockquote><blockquote type="cite" class="quoted-plain-text">}</blockquote><blockquote type="cite" class="quoted-plain-text">```</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">With `guard`, we have to repeat the parameter names meaninglessly.</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">```</blockquote><blockquote type="cite" class="quoted-plain-text">do {</blockquote><blockquote type="cite" class="quoted-plain-text">guard let firstName = json["firstName"].string else { throw Error() }</blockquote><blockquote type="cite" class="quoted-plain-text">guard let lastName = json["lastName"].string else { throw Error() }</blockquote><blockquote type="cite" class="quoted-plain-text">guard let age = json["age"].string else { throw Error() }</blockquote><blockquote type="cite" class="quoted-plain-text">let person: Person = Person(firstName: firstName, lastName:</blockquote><blockquote type="cite" class="quoted-plain-text">lastName, age: age)</blockquote><blockquote type="cite" class="quoted-plain-text">} catch _ {</blockquote><blockquote type="cite" class="quoted-plain-text">// Error handling</blockquote><blockquote type="cite" class="quoted-plain-text">}</blockquote><blockquote type="cite" class="quoted-plain-text">```</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">`guard` is a statement. `???` makes an expression. Expressions are</blockquote><blockquote type="cite" class="quoted-plain-text">useful when we want to pass their return values as arguments directly.</blockquote><blockquote type="cite" class="quoted-plain-text">I think `???` is valuable to get an unwrapped value or throw an error</blockquote><blockquote type="cite" class="quoted-plain-text">as an expression.</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">-- Yuta</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">2016-04-07 2:45 GMT+09:00 Jordan Rose via swift-evolution</blockquote><blockquote type="cite" class="quoted-plain-text"><swift-evolution@swift.org>:</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">I think I'm with Sean on this one. Optionals and throwing don't have enough</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">to do with each other to actually come up with a specific operator or method</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">for this. I can't help but see this as two ideas glued together:</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">- "By this point in my execution I need a non-optional value, otherwise</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">______"</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">- "_____ happened, therefore execution has failed and I should throw an</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">error"</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">…and I'm not sure these ideas coincide enough to be worth gluing together.</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">There are a lot of other ways to get a non-optional value out of an optional</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">('??', '!', and 'guard let' with some other action), and there are a lot of</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">other ways to fail besides an optional being nil (status code came back as</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">error, unexpected data, connection timeout).</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">I'd like to see some real-world examples of this before we did anything with</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">it.</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">Jordan</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">On Apr 6, 2016, at 8:00, Sean Heber via swift-evolution</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><swift-evolution@swift.org> wrote:</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">Interesting, but I’m unsure if all of it is significantly better than just</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">using the guard that is effectively inside of the operator/func that is</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">being proposed:</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">guard let value = Int("NotANumber") else { throw</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">InitializerError.invalidString }</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">It is only a couple of characters longer and already works (it’s what I use</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">currently). If guard allowed for a special single-expression variation so</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">that you didn’t need to specify the ugly braces or something, it’d look</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">prettier and be nice for a lot of other situations, too:</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">guard let value = Int("NotANumber") else: throw</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">InitializerError.invalidString</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">guard someVal < 10 else: return false</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">guard mustBeTrue() else: return</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">// etc</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">Not to derail this, but I sort of want this ability anywhere as a shorthand</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">for a single-expression block.</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">if something < 42: doThing()</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">for a in list: print(a)</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">But I imagine that’ll never fly. :P</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">l8r</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">Sean</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">On Apr 6, 2016, at 9:46 AM, Erica Sadun via swift-evolution</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><swift-evolution@swift.org> wrote:</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">Pyry Jahkola and I have been plugging away on the following which is</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">preliminary enough not to qualify as an actual draft. He prefers the Mike</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">Ash approach. I prefer the operator approach. So we have not actually</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">settled on which one we would actually propose despite how I've written this</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">up.</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">I'm putting this out there to try to gain a consensus on:</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">* Would this be a viable proposal?</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">* If so, which of the options would work best within Swift's design and</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">philosophy</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">Thanks for your feedback.</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">-- Erica</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">Introduction</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">Swift's try? keyword transforms error-throwing operations into optional</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">values. We propose adding an error-throwing nil-coalescing operator to the</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">Swift standard library. This operator will coerce optional results into</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">Swift's error-handling system.</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">This proposal was discussed on the Swift Evolution list in the name thread.</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">Motivation</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">Any decision to expand Swift's set of standard operators should be taken</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">thoughtfully and judiciously. Moving unaudited or deliberately</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">non-error-handling nil-returning methods and failable initializers into</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">Swift's error system should be a common enough use case to justify</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">introducing a new operator.</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">Detail Design</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">We propose adding a new operator that works along the following lines:</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">infix operator ??? {}</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">func ???<T>(lhs: T?, @autoclosure error: () -> ErrorType) throws -> T {</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">guard case let value? = lhs else { throw error() }</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">return value</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">}</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">The use-case would look like this:</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">do {</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">let error = Error(reason: "Invalid string passed to Integer initializer")</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">let value = try Int("NotANumber") ??? InitializerError.invalidString</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">print("Value", value)</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">} catch { print(error) }</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">Note</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">SE-0047 (warn unused result by default) and SE-0049 (move autoclosure) both</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">affect many of the snippets in this proposal</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">Disadvantages to this approach:</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">• It consumes a new operator, which developers must be trained to use</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">• Unlike many other operators and specifically ??, this cannot be chained.</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">There's no equivalent to a ?? b ?? c ?? dor a ?? (b ?? (c ?? d)).</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">Alternatives Considered</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">Extending Optional</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">The MikeAsh approach extends Optional to add an orThrow(ErrorType) method</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">extension Optional {</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">func orThrow(@autoclosure error: () -> ErrorType) throws -> Wrapped {</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">guard case let value? = self else { throw error() }</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">return value</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">}</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">}</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">Usage looks like this:</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">do {</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">let value = try Int("NotANumber")</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">.orThrow(InitializerError.invalidString)</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">print("Value", value)</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">} catch { print(error) }</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">An alternative version of this call looks like this: optionalValue.or(throw:</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">error). I am not a fan of using a verb as a first statement label.</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">Disadvantages:</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">• Wordier than the operator, verging on claustrophobic, even using Swift's</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">newline dot continuation.</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">• Reading the code can be confusing. This requires chaining rather than</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">separating error throwing into a clear separate component.</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">Advantages:</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">• No new operator, which maintains Swift operator parsimony and avoids the</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">introduction and training issues associated with new operators.</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">• Implicit Optional promotion cannot take place. You avoid mistaken usage</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">like nonOptional ??? error and nonOptional ?? raise(error).</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">• As a StdLib method, autocompletion support is baked in.</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">Introducing a StdLib implementation of raise(ErrorType)</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">Swift could introduce a raise(ErrorType) -> T global function:</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">func raise<T>(error: ErrorType) throws -> T { throw error }</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">do {</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">let value = try Int("NotANumber") ??</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">raise(InitializerError.invalidString)</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">print("Value", value)</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">} catch { print(error) }</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">This is less than ideal:</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">• This approach is similar to using && as an if-true condition where an</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">operator is abused for its side-effects.</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">• It is wordier than the operator approach.</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">• The error raising function promises to return a type but never will, which</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">seems hackish.</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">Overriding ??</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">We also considered overriding ?? to accept an error as a RHS argument. This</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">introduces a new way to interpret ?? as meaning, "throw this error instead</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">of substituting this value".</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">func ??<T>(lhs: T?, @autoclosure error: () -> ErrorType) throws -> T {</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">guard case let value? = lhs else { throw error() }</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">return value</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">}</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">Usage:</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">let value = try Int("NotANumber") ?? Error(reason: "Invalid string passed to</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">Integer initializer")</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">This approach overloads the semantics as well as the syntax of the</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">coalescing operator. Instead of falling back to a RHS value, it raises the</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">RHS error. The code remains simple and readable although the developer must</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">take care to clarify through comments and naming which version of the</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">operator is being used.</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">• While using try in the ?? statement signals that a throwing call is in</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">use, it is insufficient (especially when used in a throwing scope) to</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">distinguish between the normal coalescing and new error-throwing behaviors.</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">• Error types need not use the word "Error" in their construction or use.</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">For example try value ?? e may not be immediately clear as an error-throwing</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">intent.</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">• Overloading ?? dilutes the impact and meaning of the original operator</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">intent.</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">Future Directions</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">We briefly considered something along the lines of perl's die as an</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">alternative to raise using fatalError.</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">Acknowledgements</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">Thanks Mike Ash, Jido, Dave Delong</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">_______________________________________________</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">swift-evolution mailing list</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><a href="mailto:swift-evolution@swift.org" data-mce-href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br data-mce-bogus="1"></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" data-mce-href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br data-mce-bogus="1"></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">_______________________________________________</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">swift-evolution mailing list</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><a href="mailto:swift-evolution@swift.org" data-mce-href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br data-mce-bogus="1"></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" data-mce-href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br data-mce-bogus="1"></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">_______________________________________________</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">swift-evolution mailing list</blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><a href="mailto:swift-evolution@swift.org" data-mce-href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br data-mce-bogus="1"></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" data-mce-href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br data-mce-bogus="1"></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">_______________________________________________</blockquote><blockquote type="cite" class="quoted-plain-text">swift-evolution mailing list</blockquote><blockquote type="cite" class="quoted-plain-text"><a href="mailto:swift-evolution@swift.org" data-mce-href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br data-mce-bogus="1"></blockquote><blockquote type="cite" class="quoted-plain-text"><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" data-mce-href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br data-mce-bogus="1"></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote><blockquote type="cite" class="quoted-plain-text">_______________________________________________</blockquote><blockquote type="cite" class="quoted-plain-text">swift-evolution mailing list</blockquote><blockquote type="cite" class="quoted-plain-text"><a href="mailto:swift-evolution@swift.org" data-mce-href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br data-mce-bogus="1"></blockquote><blockquote type="cite" class="quoted-plain-text"><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" data-mce-href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br data-mce-bogus="1"></blockquote><blockquote type="cite" class="quoted-plain-text"><br></blockquote></span></div></div></blockquote></div></div></body></html>