> 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

Reply via email to