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