> On May 1, 2017, at 9:01 AM, Rod Brown via swift-evolution 
> <[email protected]> wrote:
> 
> On 1 May 2017, at 8:16 pm, Gor Gyolchanyan <[email protected] 
> <mailto:[email protected]>> wrote:
> 
>> Yeah, you’re absolutely right. the “value-or-nil” and 
>> “value-or-reason-why-not-value” are two different things and the former is 
>> used too liberally in place of the latter because of lack of support.
>> In that case, the Result type should not replace the error handling, but 
>> augment it. The error handling mechanism is extremely well though-out and 
>> convenient for its purpose, but it makes it difficult to capture and store a 
>> union of (value; flying error).
> 
> I agree that the key problem with the current architecture that you're 
> alluding to is it can't be easily stored and transferred. Swift errors are 
> great for live action but holding and passing after the throwing event is 
> problematic, and this is an elegant solution. The storage issue is when 
> holding it as a property, and the transferring issue is when passing it to a 
> closure as a results of an asynchronous operation etc. These are both 
> definitely cases where storage of the type-or-error makes perfect sense.
> 
> I think the key problem getting this accepted by the Swift Team will be that 
> it doesn't currently have any specific use in the standard library. As a low 
> level set of types, errors are generated by the lower levels but rarely 
> stored, so the Standard library doesn't need the storage. Generally the only 
> place we have to do that is in end user code. And currently the standard 
> library doesn't have to support asynchronous operations natively, so there's 
> nothing inside the kit that would require it to do completion handlers with 
> errors.

We've definitely considered including a Result type, but our sense was that in 
an ideal world almost no code would be using it.  It's hard to imagine an 
ordinary API that ought to be returning a Result rather than throwing, and once 
you've defined that away, the major remaining use case is just to shift 
computation around, like with a completion handler.  That explicit 
computation-shifting pattern is something we're hoping to largely define away 
with something like C#'s async/await, which would leave Result as mostly just 
an implementation detail of such APIs.  We didn't want to spend a great deal of 
time designing a type that would end up being so marginal, especially if the 
changing role would lead us into different directions on the design itself.  We 
also didn't want to design a type that would become an obstacle to potential 
future language changes like, say, typed throws.

The downside, of course, is that as long as we lack that async/await design, 
computation-shifting isn't real great.

John.

> 
> This would therefore be an element in the standard library purely so we don't 
> have 50,000 different libraries with 50,000 different result types. I'd love 
> to see this standardised so frameworks were more compatible. I'm just not 
> sure whether the Core Team would see it as pressing to try and officiate a 
> certain type that they themselves don't use.
> 
> 
>> A built-in Failable enum with syntactic support to losslessly catch it from 
>> a throwing expression and unpack it into a throwing scope would be a very 
>> useful feature.
>> Optionals are extremely convenient, but in cases where the Optional is used 
>> as “value-or-error” rather then “value-or-nil” it falls a bit short and the 
>> programmer has to choose between extreme convenience of Optionals with the 
>> downside of lack of error information or the expressive power of throwing an 
>> error with the downside of a lot of boilerpate and poor integration with 
>> generics.
>> Here’s an example pseudo-swift that illustrates this:
>> 
>> enum Failable<Wrapped> {
>>      
>>      case success(Wrapped)
>> 
>>      case failure(Error)
>> 
>> }
>> 
>> func foo() throws -> Int {
>>      guard myCondition else {
>>              throw EmbarressingError.oops
>>      }
>>      return 42
>> }
>> 
>> let failable = catch foo() // Failable<Int>
>> 
>> func bar() throws -> Int {
>>      throw failable
>> 
>> 
>> 
>>> On May 1, 2017, at 11:17 AM, Rod Brown <[email protected] 
>>> <mailto:[email protected]>> wrote:
>>> 
>>> The problem I see with your argument is that the core reason why the 
>>> optional cast failed is actually there: It was an optional value, and you 
>>> forced it to unwrap without checking. This is a correct description of the 
>>> error.
>>> 
>>> If we plumbed our code with a tonne of errors saying “why this is optional, 
>>> and why it is null” then we are practically making every optional an error 
>>> in the case of nil, which is completely illogical considering that nil 
>>> could be a completely legitimate case (especially in the case of 
>>> not-implicitly-unwrapped optionals).
>>> 
>>> Optional is a wrapper for "value-or-null", not "value-or-reason-not-value".
>>> 
>>> The type you are talking about is a result/sum type as has been mentioned, 
>>> which is fine, and is completely valid (I use them a lot too) but they are 
>>> definitely not the same thing as an optional, and I think you’re conflating 
>>> the two ideas.
>>> 
>>> - Rod
>>> 
>>> 
>>>> On 1 May 2017, at 5:58 pm, Gor Gyolchanyan via swift-evolution 
>>>> <[email protected] <mailto:[email protected]>> wrote:
>>>> 
>>>> I have read those documents before, but It’s worth re-reading them to see 
>>>> if I missed something, but I’l still explain my motivation and seek 
>>>> arguments against the postulated problem (rather then a specific solution).
>>>> 
>>>> (a) There are different types of error.
>>>> 
>>>> Yes, there are different types of error in Swift, which require different 
>>>> reactions from the programmer.
>>>> If I’m not missing something, the three main types of error in Swift are:
>>>>  - Simple encapsulatable errors that are expected to be treated as normal 
>>>> values until the time comes for someone to take care of them by unpacking 
>>>> the content.
>>>>  - Automatic propagatable errors that require the programmer to either 
>>>> handle the error immediately or propagate it by delegating to its own 
>>>> caller.
>>>> - Fatal errors, which represent logic errors and broken invariants and 
>>>> preconditions, which are purely a programmer error and should not be dealt 
>>>> with dynamically, hence the terminated process with a message.
>>>> 
>>>> (b) The programmer is expected to react differently to different types of 
>>>> error.
>>>> 
>>>> Yes, and the three main ways a programmer is expected to react to the an 
>>>> error are:
>>>>  - If it’s an optional, they’re encouraged to store and pass it around 
>>>> freely until someone down the line decides to unpack it and deal with the 
>>>> possibility that it isn’t there.
>>>>  - If it’s an error, they’re encouraged to either handle it on the spot or 
>>>> declare themselves throwing and delegate the responsibility to the caller.
>>>>  - Look at the standard output and figure out why the fatal error 
>>>> occurred, perhaps with the help of the debugger.
>>>> 
>>>> (c) The language is a tool to help the programmer react.
>>>> 
>>>> Yes, that comes in the form of three language constructs:
>>>>  - Optionals, which allow storing a union of a value and its absence (for 
>>>> an undefined and hopefully obvious reason).
>>>>  - Throwing functions, which allow making sure that the error will be 
>>>> handled as soon as possible.
>>>>  - Fatal errors, which allow the programmer to mark points in code which 
>>>> should never be reached in a correct system in order to keep the logic 
>>>> from going AWOL in case the programmer screwed up somewhere.
>>>> 
>>>> (d) Optionals and errors are not unified, and unification is a non-goal, 
>>>> because they are designed to help the programmer react differently to 
>>>> different types of error.
>>>> 
>>>> Yes, and those different types of error with different reactions are all 
>>>> valid and shouldn’t be unified.
>>>> My point is that the language should make it easy for a programmer to 
>>>> transition from one type of error to another, because the same error has 
>>>> different severity in different contexts.
>>>> For instance, a “file not found” error when trying to open a file handler 
>>>> is not critical at all in the context of the file opening function, 
>>>> because it’s a perfectly expected outcome of the operation.
>>>> However, for a module that handles loading critical data from disk (like 
>>>> encryption keys needed to decrypt the manipulated content) it is a 
>>>> critical error that cannot be dealt with.
>>>> In this case it deserves to be a fatal error, because the programmer 
>>>> didn’t bother to implement a logic for creating the missing file or 
>>>> properly notifying the user of the lacking permissions to do so.
>>>> Conversely, some errors start as being urgent (like a JSON parser that 
>>>> throws an error when it encounters invalid syntax), but become less urgent 
>>>> for the client (a JSON editor that simply displays the error message).
>>>> 
>>>> As for my use case:
>>>> 
>>>> I have a JSON parser that may throw, and I have a a JSON Editor class that 
>>>> allows editing JSON files as well as displaying the parsing errors.
>>>> I have a malformed JSON file that I open in the editor. The JSON parser 
>>>> throws an error, which should be caught and stored somewhere for the 
>>>> editor to display.
>>>> I have file reader that reads a file in some encoding and returns an 
>>>> optional string with the file contents (nil means file couldn’t be read or 
>>>> the encoding is wrong).
>>>> 
>>>> For the JSON parser, a malformed JSON file is an obvious error, but for 
>>>> the editor, it’s a perfectly valid and expected condition, which doesn’t 
>>>> deserve to be an error.
>>>> Therefore, the thrown error of the JSON parse has to be caught and 
>>>> encapsulated indiscriminately to demote it from an error to a return value.
>>>> Conversely, the returned nil form the file reader is perfectly valid and 
>>>> expected condition, but for the editor, it’s an error.
>>>> Therefore, the returned nil should be checked and converted to an error 
>>>> that will be thrown to promote it to a full-fledged error.
>>>> 
>>>> I would want to have a way to easily promote/demote different types of 
>>>> errors to accommodate the changing perception of their urgency.
>>>> For instance, by being able to throw an optional, thus introducing a new 
>>>> way of unpacking it (by promoting it to an error). Currently, it is by 
>>>> manually unpacking the optional, deciding what error to throw and throwing 
>>>> it manually.
>>>> Or, being able to catch an error into an optional, thus introducing a new 
>>>> way of handling it (by demoting it to an optional). There is a way to do 
>>>> that currently in the form of `try?` and `try!`, but their downside is 
>>>> that they are lossy (losing the error itself).
>>>> 
>>>> All I want is for the language to help me losslessly catch errors into 
>>>> something like an optional, except with the error intact with the 
>>>> possibility of easily re-throwing it in the future.
>>>> This would also solve the problem of multiple throwing calls having 
>>>> different urgency to them and being forced to write a lot of boilerplate 
>>>> to catch their errors individually and deal with them separetely.
>>>> 
>>>>> On May 1, 2017, at 1:44 AM, Xiaodi Wu <[email protected] 
>>>>> <mailto:[email protected]>> wrote:
>>>>> 
>>>>> On Sun, Apr 30, 2017 at 5:05 PM, Gor Gyolchanyan <[email protected] 
>>>>> <mailto:[email protected]>> wrote:
>>>>> 
>>>>>> On May 1, 2017, at 12:10 AM, Xiaodi Wu <[email protected] 
>>>>>> <mailto:[email protected]>> wrote:
>>>>>> 
>>>>>> You may wish to read the rationale behind the current error handling 
>>>>>> design:
>>>>>> 
>>>>>> https://github.com/apple/swift/blob/master/docs/ErrorHandlingRationale.rst
>>>>>>  
>>>>>> <https://github.com/apple/swift/blob/master/docs/ErrorHandlingRationale.rst>
>>>>>> 
>>>>>> A Result type like you suggest has been considered and rejected in favor 
>>>>>> of the current design. Briefly, optionals and throwing errors are 
>>>>>> distinct because they are considered superior ways for handling distinct 
>>>>>> types of error.
>>>>>> 
>>>>>> In the case of a simple domain error, there is only one way to fail; 
>>>>>> therefore, optional return values are considered the best way to model 
>>>>>> that error.
>>>>>> 
>>>>>> In the case of a recoverable error, the document above describes why 
>>>>>> marked propagation (the current implementation in Swift) is considered 
>>>>>> superior to typed propagation (your suggestion).
>>>>> 
>>>>> 
>>>>> My proposal is not about replacing Optionals and throwing functions with 
>>>>> a Result type, it’s about separating the representation of an error from 
>>>>> its propagation.
>>>>> Optionals and throwing functions solve two different problems, but they 
>>>>> are not dealing with two different types of error.
>>>>> 
>>>>> The basic premise of Swift error handling design is that there exist 
>>>>> different types of error. From the document:
>>>>> 
>>>>> > What is an error? There may be many different possible error conditions 
>>>>> > in a program, but they can be categorized into several kinds based on 
>>>>> > how programmers should be expected to react to them. Since the 
>>>>> > programmer is expected to react differently, and since the language is 
>>>>> > the tool of the programmer's reaction, it makes sense for each group to 
>>>>> > be treated differently in the language.
>>>>> 
>>>>> Optionals are for storing and representing a value that might not exist 
>>>>> (most commonly due to an unambiguous error).
>>>>> Error handling is for propagating an error.
>>>>> Returning an optional is essentially the same as returning a non-optional 
>>>>> and throwing a dedicated “something went wrong” error, because due to the 
>>>>> optional unwrapping mechanic, you cannot avoid dealing with the fact that 
>>>>> there might have been an error. Optionals only allow you to delay the 
>>>>> inevitable error handling, not avoid it. The use cases where the exact 
>>>>> reason for an error is no important have nothing to do with whether or 
>>>>> not that error should be available. The optional chaining, if-let 
>>>>> statements and all other ways one might try to handle an optional value 
>>>>> do not fundamentally require lack of error information.
>>>>> The error handling mechanism, on the other hand, does not concern itself 
>>>>> with representing the error, but only propagating it. Even an optional 
>>>>> value with a general-purpose .none case has different levels of 
>>>>> importance in different cases. More often than not, when propagating an 
>>>>> optional value to a non-optional target, you’ll be stuck with dealing 
>>>>> with the error immediately, which is exactly what throwing functions 
>>>>> force you to do.
>>>>> I suggest we enhance the current error representation and propagation 
>>>>> mechanisms to be able to seamlessly handle cases where an erroneous value 
>>>>> need to be stored as-is (along with its error) or unpacked and propagated 
>>>>> (by throwing the error), not just representing a general “error”.
>>>>> The general use case is to be able to catch a throwing call into an enum 
>>>>> that stores the value or the error and then being able to unpack it in a 
>>>>> throwing context (unpack it or throw the error).
>>>>> This use case is a strict superset of the current Optional mechanic 
>>>>> (catching a potentially missing value) and error handling (always 
>>>>> manually throwing an error after manual checks).
>>>>> The aforementioned suggestion about how to do that is indeed faulty, as 
>>>>> pointed out by Robert Widmann, but the problem is still valid, in my 
>>>>> opinion.
>>>>> 
>>>>> I'd highly recommend taking some time to digest the existing rationale. 
>>>>> You're basing your argument on contradicting the fundamental premise of 
>>>>> the existing design, which begins with this: (a) there are different 
>>>>> types of error; (b) the programmer is expected to react differently to 
>>>>> different types of error; (c) the language is a tool to help the 
>>>>> programmer react; (d) optionals and errors are not unified, and 
>>>>> unification is a non-goal, because they are designed to help the 
>>>>> programmer react differently to different types of error.
>>>>> 
>>>>> Do you have a specific use case in mind that is not well accommodated by 
>>>>> optionals or by throwing functions? What is it? Into what category does 
>>>>> that use case fall, in terms of the types of error enumerated in the 
>>>>> error handling rationale document?
>>>>> 
>>>>>> On Sun, Apr 30, 2017 at 13:51 Gor Gyolchanyan via swift-evolution 
>>>>>> <[email protected] <mailto:[email protected]>> wrote:
>>>>>> 
>>>>>> > On Apr 30, 2017, at 9:29 PM, Robert Widmann <[email protected] 
>>>>>> > <mailto:[email protected]>> wrote:
>>>>>> >
>>>>>> >
>>>>>> >> On Apr 30, 2017, at 1:43 PM, Gor Gyolchanyan <[email protected] 
>>>>>> >> <mailto:[email protected]>> 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.
>>>>>> 
>>>>>> Yeah, you’re right. It would take some next-level fixits to deal with 
>>>>>> the consequences of changing the most fundamental data type of Swift I 
>>>>>> can think of.
>>>>>> I’d really appreciate it if you’d offer an alternative solution to this 
>>>>>> problem.
>>>>>> The problem, as I understand it, is as follows:
>>>>>> 
>>>>>> A lot of Swift’s logic revolves around the notion that some values might 
>>>>>> be missing for whatever reason and some functions might fail for 
>>>>>> whatever reason.
>>>>>> Any function’s effect can be summed up as the union of its return value 
>>>>>> and the global state that it changes (that includes captured closure 
>>>>>> scopes).
>>>>>> This could be boiled down to the statement that “Values that a function 
>>>>>> sets and returns completely express the purpose of the function”.
>>>>>> The optional gives an extremely convenient way of representing values 
>>>>>> that might not exist (which, when returned from a function often means 
>>>>>> “failed for an unknown reason”).
>>>>>> The fact that Optional is a type, rather then a function attribute 
>>>>>> allows us to store and imperatively manipulate the outcome of logically 
>>>>>> failable functions, but unfortunately, it doesn’t allow us to reason 
>>>>>> about the cause of the failure.
>>>>>> On the other hand, throwing functions captures the logic of dealing with 
>>>>>> specific failures very well, but does not allow us to store and 
>>>>>> manipulate them easily, leaving us with workarounds like wrapping errors 
>>>>>> in enums with values and re-throwing the errors on their way out of the 
>>>>>> generic pipeline.
>>>>>> I’d like to come up with a solution that would unify the optionals and 
>>>>>> the throwing functions into a single mechanism for dealing with the 
>>>>>> concept of failure, taking the best of both worlds and getting the 
>>>>>> benefits of the new synergies.
>>>>>> This pitch was a first rough idea about the direction in which we could 
>>>>>> go in trying to find a solution.
>>>>>> I chose to enhance Optional instead of introducing a new type like 
>>>>>> Failable, so that we could make do with minimal language changes and 
>>>>>> migration procedures.
>>>>>> 
>>>>>> This problem is kinda similar to the variadic parameter problem, which 
>>>>>> makes it impossible to forward calls to variadic functions simply 
>>>>>> because that feature is too magical and does not provide a way to store 
>>>>>> and propagate its logic.
>>>>>> 
>>>>>> Another way I could think of solving it would be to allow overloading 
>>>>>> the postfix `!` and `?` operators (which would currently only be defined 
>>>>>> for Optionals), which would allow us to define the Failable enum type 
>>>>>> with some error handling syntax integration and make it feel more at 
>>>>>> home in the midst of Optionals.
>>>>>> 
>>>>>> Or better yet, make an OptionalProtocol and move the current magical 
>>>>>> logic to it, leaving the existing Optional perfectly intact and allowing 
>>>>>> userspace implementations.
>>>>>> This would also greatly benefit numerous use cases of “invalidatable” 
>>>>>> types (like file handlers that can be closed) that would no longer have 
>>>>>> to either fatalError or use unwieldy wrappers that operate on Optionals.
>>>>>> 
>>>>>> > ~Robert Widmann
>>>>>> >
>>>>>> >>
>>>>>> >>> On Apr 30, 2017, at 8:35 PM, Robert Widmann 
>>>>>> >>> <[email protected] <mailto:[email protected]>> 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 
>>>>>> >>> <[email protected] <mailto:[email protected]>> 
>>>>>> >>> のメッセージ:
>>>>>> >>>
>>>>>> >>>> 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
>>>>>> >>>> [email protected] <mailto:[email protected]>
>>>>>> >>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>>>> >>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>>>> >>
>>>>>> >
>>>>>> 
>>>>>> _______________________________________________
>>>>>> swift-evolution mailing list
>>>>>> [email protected] <mailto:[email protected]>
>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>> _______________________________________________
>>>> swift-evolution mailing list
>>>> [email protected] <mailto:[email protected]>
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>> 
>> 
> _______________________________________________
> swift-evolution mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to