Well, the whole point was to make error handling syntax and semantics less magical and more generic-friendly, so you’re right, it is essentially a new sum type with error handling syntax on top of it. Except, adding it alongside optional would introduce accidental complexity to swift’s “unexpected situations” mechanism. It doesn’t have to be a massive source-break, since this pitch is supposed to be a strict superset of what Optional and throwing is currently. The only thing that I can think of at this moment that would break is this syntax:
let foo: Int? = .none // Error: Can’t convert (Error) -> Int? to Int? The ExpressibleByNilLiteral, the try/throw syntax, all of those things would work as they are right now. Error handling as it is currently, is essentially a hidden `error` out parameter and a whole bunch of codegen. Even the semantical changes described earlier would be purely additive. > On Apr 30, 2017, at 8:35 PM, Robert Widmann <devteam.cod...@gmail.com> wrote: > > This "revamp" is isomorphic to adding a Sum type to stdlib and plumbing error > handling syntax through. I'd much rather see that than the massive > source-break this would entail. > > ~Robert Widmann > > 2017/04/30 13:11、Gor Gyolchanyan via swift-evolution > <swift-evolution@swift.org> のメッセージ: > >> I’d like to suggest a bit of redesigning the Optional type and throwing >> functions to provide a single powerful and flexible mechanism for dealing >> with unexpected situations. >> >> In short, The Optional would have an associated value of type Error added to >> its `none` case, which would describe the reason why the wrapped value is >> missing. >> >> public enum Optional<Wrapped> { >> >> case .some(Wrapped) >> >> case .none(Error) >> >> } >> >> The Optional's ExpressibleByNilLiteral would initialize it with an error >> that corresponds to what is currently fatalError-ed as "unexpectedly found >> nil while unwrapping an Optional value". >> >> The forced unwrapping operator (postfix `!`) would behave the same way as it >> does now, except in case of a fatal error it would print out the underlying >> error, instead of the aforementioned hard-coded string. >> >> The optional chaining operator (postfix `?`) would behave the same way as it >> does now, except when it stops evaluating and returns the Optional, it would >> contain the error, returned by the sub-expression that failed to evaluate. >> >> Any throwing function would be equivalent to a function that returns an >> Optional. If the function is declared as throwing and returning an Optional >> at the same time, it would be equivalent to a function returning an Optional >> Optional. >> >> The if-let statement would bind the `let` variable to the wrapped value >> inside the "then" block and would bind it to the error in the "else" block. >> Chained else-if blocks would all be considered part of the overarching >> "else" block, so all of them would be able to access the error bound to the >> if-let name. >> >> The guard-let and case-let statements are essentially just rewrites of >> if-let with some added logic. >> >> The `try` keyword, applied to an optional would behave like this: >> >> public func try<T>(_ optional: T?) throws -> T { >> guard let wrapped = optional else { >> throw wrapped // Remember, if-let, guard-let and case-let statements >> bind the let name to the error in case of a failure. >> } >> return wrapped >> } >> >> Multiple let bindings in a single if-let statement are essentially rewrites >> of a nested chain of if-let statements. >> >> The `try` keyword applied to an optional would unwrap the value or throw the >> error. >> The `try?` keyword applied to a throwing function call would cause any >> thrown errors to be caught and put into the returned Optional, instead of >> simply ignored. >> The `try!` keyword applied to a throwing function call would behave as you'd >> expect: just like `try?` except immediately force-unwrapped. >> >> A throwing function would be convertible to a non-throwing >> optional-returning function and vice versa. >> This would allow making use of throwing functions when dealing with generics >> or protocols that allow arbitrary return types, without having to sacrifice >> the convenience of error-handling logic. Conversely, it would allow to write >> generic code that deals with any type of function without having to >> implement special cases for throwing functions. This means that the two >> function types would be interchangeable and one would be able to satisfy >> protocol requirements of the other. The `rethrows` idiom would then become a >> natural consequence of writing generic functions that may return optional >> and non-optional results just as well. >> >> _______________________________________________ >> 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