> On Apr 30, 2017, at 1:43 PM, Gor Gyolchanyan <g...@gyolchanyan.com> wrote: > > 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? >
Except it’s not a strict superset if you break every use of this case as an RValue. Especially when so much of Swift’s syntax and major patterns revolve around the manipulation of optionals. > 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. Don’t get me wrong, I think you’ve identified the problem space well, I just disagree with the solution. ~Robert Widmann > >> 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