SE-0235 - Add Result to the Standard Library

What is your evaluation of the proposal?

-1

Is the problem being addressed significant enough to warrant a change to Swift?

It depends which problem specifically is being addressed by Result. Essentially all of the compelling cases I see involve asynchronous code. Error propagation in such code is certainly a really big problem, but I don't think this is necessarily the best solution. See below.

Does this proposal fit well with the feel and direction of Swift?

I don't think so. The idea of using a Result type comes from the pattern of using completion-handler closures. That is, people are (rightly) dissatisfied with this:

performOperation(with: value, completion: { (result: Int?, error: Error?)->Void in
})

and want to write it more like this, to express that the result and error values are mutually exclusive:

performOperation(with: value, completion: { (result: Result<Int, Error>)->Void in
})

So the real question is whether we are happy sticking with the completion-handler pattern as our concurrency model. AFAIK, that model was inherited from Obj-C and its ultimate fate is still unresolved; I have heard plenty of good arguments for using an async/await model instead. So the above code would become:

let result: Int = try await performOperation(with: value)

With no Result type needed at all.

I entirely sympathise with people who are frustrated with the lack of a language-integrated concurrency model in Swift, and have turned to Result<T> as a workaround. Likewise, I know the pain of having to constantly map to/fro between equivalent types from multiple libraries. The truth, though, is that baking this workaround in to the standard library and ABI is entirely premature.

I also consider this is a backdoor way to introduce typed throws in the language, which I'm also against.

Additionally, as @soroush mentioned, I think it's obvious that people will want this type to gain special language support - from if let syntax to implicit conversions between (A) throws -> B and (A)->Result<B, Error>, and maybe even from Result<T> to Optional<T>. I think this is a very slippery slope.

If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

I can't directly compare it with anything I've used before, but in general I strongly dislike typed exceptions in languages such as Java. I find that it greatly increases coupling, with little/no benefit; Errors are almost never handled exhaustively.

How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Participated in this and previous discussions, including about typed-throws and the concurrency model in general.

22 Likes