# \[Bikeshedding\]: Supporting throwing transforms on Result

**URL:** <https://forums.swift.org/t/bikeshedding-supporting-throwing-transforms-on-result/21698>\
**Category:** Discussion\
**Created:** [March 17, 2019, 4:19am UTC](https://forums.swift.org/t/bikeshedding-supporting-throwing-transforms-on-result/21698 "2019-03-17T04:19:37Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jon\_Shier](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jon_shier/32/921_2.png) [@Jon\_Shier](https://forums.swift.org/u/Jon_Shier)\
**Post date:** [March 17, 2019, 4:19am UTC](https://forums.swift.org/t/bikeshedding-supporting-throwing-transforms-on-result/21698/1 "2019-03-17T04:19:37Z")

</div>

During the review of SE-0235, which added `Result` to the standard library, the core team felt that there was no satisfactory name for a transform that supports throwing closures. Without such a transform, `Result` is left with this abomination:

```swift
let network: Result<Data, Error> = .success(responseData)
let decoded: Result<Response, Error> = network.flatMap { (data) in
    Result {
        try JSONDecoder().decode(Response.self, from: data)
    }
}

```

This is the simplest version of this transform and already it's highly confusing and easy to produce compiler errors due to type mismatches. More complex transforms are even worse. So I'd like to come up with a suitable name for the operation.

To my mind, `flatMap` works fine, as we're flattening either a `Result` into a `Result` or a throwing closure into a `Result`. I think the equivalence makes sense and the overload would be pretty easy to add. I also thought about `compactMap`, but it doesn't really make sense given the current usage, as nothing could be removed.

Any other ideas?

---

<div class="post-metadata">

**Author:** ![lukasa](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/lukasa/32/1232_2.png) [@lukasa](https://forums.swift.org/u/lukasa)\
**Post date:** [March 17, 2019, 2:37pm UTC](https://forums.swift.org/t/bikeshedding-supporting-throwing-transforms-on-result/21698/2 "2019-03-17T14:37:56Z")

</div>

This is not a million miles away from the situation NIO has with its `EventLoopFuture` type, which in NIO 2 will have the following functions (and the equivalent `Error` versions for transforming the error case):

```swift
public func map<NewValue>(_ callback: @escaping (Value) -> (NewValue)) -> EventLoopFuture<NewValue>
public func flatMap<NewValue>(_ callback: @escaping (Value) -> EventLoopFuture<NewValue>) -> EventLoopFuture<NewValue>
public func flatMapThrowing<NewValue>(_ callback: @escaping (Value) throws -> NewValue) -> EventLoopFuture<NewValue>

```

Our spelling of what you're proposing is `flatMapThrows`, so it may be worth adding that to the list of prior art. If the community decides to go a different way with that name, we'll likely adopt the consensus name in the future for our version.

---

<div class="post-metadata">

**Author:** ![michelf](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/michelf/32/1180_2.png) [@michelf](https://forums.swift.org/u/michelf)\
**Post date:** [March 17, 2019, 2:53pm UTC](https://forums.swift.org/t/bikeshedding-supporting-throwing-transforms-on-result/21698/3 "2019-03-17T14:53:01Z")

</div>

My preferred way to handle cases like this is to use `network.get()` to propagate the error to the newer result via throwing:

```swift
let network: Result<Data, Error> = .success(responseData)
let decoded = Result {
    try JSONDecoder().decode(Response.self, from: network.get())
}

```

I just have to write the happy path and let the errors propagate themselves. But I understand this style might not be to everyone's liking.

---

<div class="post-metadata">

**Author:** ![bzamayo](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/bzamayo/32/764_2.png) [@bzamayo](https://forums.swift.org/u/bzamayo)\
**Post date:** [March 18, 2019, 12:19pm UTC](https://forums.swift.org/t/bikeshedding-supporting-throwing-transforms-on-result/21698/4 "2019-03-18T12:19:18Z")

</div>

In my Swift 5 branches, I am provisionally using `attemptMap` (behaves the same as `map` with a throwing closure and returns `Result<NewSuccess, Error>`) for lack of a better name.

---

<div class="post-metadata">

**Author:** ![sveinhal](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/sveinhal/32/3992_2.png) [@sveinhal](https://forums.swift.org/u/sveinhal)\
**Post date:** [March 18, 2019, 12:39pm UTC](https://forums.swift.org/t/bikeshedding-supporting-throwing-transforms-on-result/21698/5 "2019-03-18T12:39:14Z")

</div>

> [@bzamayo](#):
>
> In my Swift 5 branches, I am provisionally using `attemptMap`

I’m not even sure if I advocate it, but to me `tryMap` feels better aligned by current terminology, should we go down this path.

Although I think I prefer to just overload `flatMap`.

---

<div class="post-metadata">

**Author:** ![bzamayo](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/bzamayo/32/764_2.png) [@bzamayo](https://forums.swift.org/u/bzamayo)\
**Post date:** [March 18, 2019, 1:59pm UTC](https://forums.swift.org/t/bikeshedding-supporting-throwing-transforms-on-result/21698/6 "2019-03-18T13:59:19Z")

</div>

Yeah, I'd be happy with any throwing overload that lets the client return `NewSuccess` (or throw) in the transformation closure. `flatMap` seems appropriate.

---

<div class="post-metadata">

**Author:** ![John\_McCall](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/john_mccall/32/1351_2.png) [@John\_McCall](https://forums.swift.org/u/John_McCall)\
**Post date:** [March 18, 2019, 4:38pm UTC](https://forums.swift.org/t/bikeshedding-supporting-throwing-transforms-on-result/21698/7 "2019-03-18T16:38:38Z")

</div>

> [@michelf](#):
>
> My preferred way to handle cases like this is to use `network.get()` to propagate the error to the newer result via throwing:

This is exactly what I would recommend, and I really don't understand the resistance to it.

---

<div class="post-metadata">

**Author:** ![Jon\_Shier](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jon_shier/32/921_2.png) [@Jon\_Shier](https://forums.swift.org/u/Jon_Shier)\
**Post date:** [March 18, 2019, 4:43pm UTC](https://forums.swift.org/t/bikeshedding-supporting-throwing-transforms-on-result/21698/8 "2019-03-18T16:43:00Z")

</div>

It’s not possible to use this pattern in chained transforms, as you always have to break the chain to do it. At this point Result has nearly 5 years of usage in the community, so I’m trying to match how it’s usage has evolved in that time to the constraints of the standard library. Using `get` as suggested has been possible for a long time and yet has not caught on, suggesting that it’s not how most Result users want to use the type.

---

<div class="post-metadata">

**Author:** ![John\_McCall](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/john_mccall/32/1351_2.png) [@John\_McCall](https://forums.swift.org/u/John_McCall)\
**Post date:** [March 18, 2019, 5:54pm UTC](https://forums.swift.org/t/bikeshedding-supporting-throwing-transforms-on-result/21698/9 "2019-03-18T17:54:35Z")

</div>

The only general argument against it that I know of — e.g. that `get()` erases the stronger type information of a `Result` — seems to go out the window when you merge in an arbitrary `Error` from a throwing transform.

If it's easier to apply multiple transforms to a value when it's bound up in a `Result` than it is to apply them directly to a value, that seems like a serious usability problem in Swift. But it's hard not to suspect that this is not true and people are just avoiding the idiomatic solution because they're transliterating patterns from other languages.

---

<div class="post-metadata">

**Author:** ![gwendal.roue](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/gwendal.roue/32/13992_2.png) [@gwendal.roue](https://forums.swift.org/u/gwendal.roue)\
**Post date:** [March 18, 2019, 6:39pm UTC](https://forums.swift.org/t/bikeshedding-supporting-throwing-transforms-on-result/21698/10 "2019-03-18T18:39:37Z")

</div>

> [@John\_McCall](#):
>
> But it's hard not to suspect that this is not true and people are just avoiding the idiomatic solution because they're transliterating patterns from other languages.

Hello,

"Idiomatic" doesn't sound quite right, honestly. Both Alamofire's and Antitypical's Result had support for flatMap/tryMap accepting a throwing closure, and I think they are totally entitled to define what "idiomatic" should mean here. It's not surprising that people come back when usual Result patterns are no longer provided for free.

And here it looks like replacement patterns are _less good_ (as explained by @Jon_Shier). Method chaining _is_ one of the many Swift idioms, not some foreign transliterated pattern.

---

<div class="post-metadata">

**Author:** ![xwu](https://avatars.discourse-cdn.com/v4/letter/x/b487fb/32.png) [@xwu](https://forums.swift.org/u/xwu)\
**Post date:** [March 18, 2019, 6:55pm UTC](https://forums.swift.org/t/bikeshedding-supporting-throwing-transforms-on-result/21698/11 "2019-03-18T18:55:03Z")

</div>

> [@gwendal.roue](#):
>
> "Idiomatic" doesn't sound quite right, honestly. Both Alamofire's and Antitypical's Result had support for flatMap/tryMap accepting a throwing closure, and I think they are totally entitled to define what "idiomatic" should mean here. It's not surprising that people come back when usual Result patterns are no longer provided for free.
> 
> And here it looks like replacement patterns are _less good_ (as explained by @Jon_Shier). Method chaining _is_ idiomatic Swift, not some foreign transliterated pattern.

@John_McCall is _not_ stating that method chaining isn't idiomatic Swift. You sliced out the first part of the paragraph:

> [@John\_McCall](#):
>
> If it's easier to apply multiple transforms to a value when it's bound up in a `Result` than it is to apply them directly to a value, that seems like a serious usability problem in Swift.

The idiomatic way to apply multiple transforms in Swift while propagating errors is to apply the transforms directly to a value. If that's not easier than applying multiple transforms to a value wrapped in a `Result`, then we have a big problem in Swift.

---

<div class="post-metadata">

**Author:** ![gwendal.roue](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/gwendal.roue/32/13992_2.png) [@gwendal.roue](https://forums.swift.org/u/gwendal.roue)\
**Post date:** [March 18, 2019, 7:09pm UTC](https://forums.swift.org/t/bikeshedding-supporting-throwing-transforms-on-result/21698/12 "2019-03-18T19:09:04Z")

</div>

I don't understand. Nobody has any problem with applying multiple throwing transformations. The problem lies in the frontier between Result-based apis, and regular throwing methods (which **are** the idiomatic way to transform values with eventual error). It is very simple, and has been well explained: there is no point stating it again.

A flatMap with a throwing closure has been requested during the pitch, the review, and regrets have been expressed after SE-0235 had shipped without it. The rationale did not close the door:

> [@\[Accepted with Modifications\] SE-0235: Add Result to the Standard Library](https://forums.swift.org/t/accepted-with-modifications-se-0235-add-result-to-the-standard-library/18603/1):
>
> Several members of the community voiced disappointment that the proposal did not include a variant of `flatMap` that took a throwing closure. The Core Team reaffirms its desire to never overload methods by whether an argument function can throw. We spent quite some time debating whether a different name would be acceptable, such as `flatMapThrowing` , but were unable to reach consensus on this, especially as there are alternative means of expressing this using the catching initializer.

Edit: it's just a discussion about a convenience API, nothing more... There is no "big problem in Swift"...

---

<div class="post-metadata">

**Author:** ![John\_McCall](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/john_mccall/32/1351_2.png) [@John\_McCall](https://forums.swift.org/u/John_McCall)\
**Post date:** [March 18, 2019, 7:35pm UTC](https://forums.swift.org/t/bikeshedding-supporting-throwing-transforms-on-result/21698/13 "2019-03-18T19:35:09Z")

</div>

I don't think Alamofire and Antitypical get to define the right idioms for working with `Result`. Swift is allowed to be opinionated, and the existence of a few longstanding methods (with users, even) doesn't override that. That said, of course I don't unilaterally speak for the entire project; I am providing my opinion, not trying to shut the discussion.

My opinion is that any feature which combines multiple kinds of propagation in an expression is bound to have confusing interactions, so it's better to "canonicalize" to a single kind of propagation, which probably ought to be error-throwing because it composes more naturally. And the counter-argument was that it _doesn't_ compose more naturally because chaining `flatMap`-like transforms is better than just being able to use the value directly as an expression operand.

---

<div class="post-metadata">

**Author:** ![gwendal.roue](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/gwendal.roue/32/13992_2.png) [@gwendal.roue](https://forums.swift.org/u/gwendal.roue)\
**Post date:** [March 18, 2019, 7:38pm UTC](https://forums.swift.org/t/bikeshedding-supporting-throwing-transforms-on-result/21698/14 "2019-03-18T19:38:30Z")

</div>

> [@John\_McCall](#):
>
> My opinion is that any feature which combines multiple kinds of propagation in an expression is bound to have confusing interactions

I must here confess that my own usages of flatMap with throwing closures had always looked a little too magical to me, and that I didn't feel 100% comfortable. It's very _compressed_: there are too many layers to decipher for a newcomer.

---

<div class="post-metadata">

**Author:** ![xwu](https://avatars.discourse-cdn.com/v4/letter/x/b487fb/32.png) [@xwu](https://forums.swift.org/u/xwu)\
**Post date:** [March 18, 2019, 7:39pm UTC](https://forums.swift.org/t/bikeshedding-supporting-throwing-transforms-on-result/21698/15 "2019-03-18T19:39:43Z")

</div>

> [@gwendal.roue](#):
>
> The problem lies in the frontier between Result-based apis, and regular throwing methods (which **are** the idiomatic way to transform values with eventual error). It is very simple, and has been well explained: there is no point stating it again.

It is not very simple to me; if it has been well explained, I have not seen that explanation. So indeed: it should be stated again.

* * *

That brings me to the quoted part of the decision and @Jon_Shier's interpretation:

> [@Jon\_Shier](#):
>
> During the review of SE-0235, which added `Result` to the standard library, the core team felt that there was no satisfactory name for a transform that supports throwing closures.

That is not how I read the decision note. My reading is that the core team was undecided as to whether adding such a transform would be acceptable _under any name_, not that they were undecided _as to what name_. Otherwise, the caveat at the end of their decision ("especially as there are alternative means of expressing this using the catching initializer") would be meaningless:

> [@John\_McCall](#):
>
> We spent quite some time debating whether a different name would be acceptable, such as `flatMapThrowing` , but were unable to reach consensus on this, especially as there are alternative means of expressing this using the catching initializer.

---

<div class="post-metadata">

**Author:** ![Jon\_Shier](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jon_shier/32/921_2.png) [@Jon\_Shier](https://forums.swift.org/u/Jon_Shier)\
**Post date:** [March 18, 2019, 9:26pm UTC](https://forums.swift.org/t/bikeshedding-supporting-throwing-transforms-on-result/21698/16 "2019-03-18T21:26:52Z")

</div>

> [@John\_McCall](#):
>
> I don't think Alamofire and Antitypical get to define the right idioms for working with `Result` . Swift is allowed to be opinionated, and the existence of a few longstanding methods (with users, even) doesn't override that. That said, of course I don't unilaterally speak for the entire project; I am providing my opinion, not trying to shut the discussion.

They shouldn't be used to constrain idiom going forward, but they are good examples of what the community's idioms were before `Result` was added to the standard library. In fact, Alamofire's `Result` didn't have any functional transforms for years before they were added by a contributed PR, which is rather rare. This illustrates the expectations of users who have used `Result` in Swift before, as well as the APIs they used.

> [@xwu](#):
>
> > If it's easier to apply multiple transforms to a value when it's bound up in a `Result` than it is to apply them directly to a value, that seems like a serious usability problem in Swift.
> 
> The idiomatic way to apply multiple transforms in Swift while propagating errors is to apply the transforms directly to a value. If that's not easier than applying multiple transforms to a value wrapped in a `Result` , then we have a big problem in Swift.

That it's easier to transform `Result`s by staying within `Result`s shouldn't really be surprising, any more than it would be surprising that transforming a `String` is easier with API on `String` instead of passing it somewhere else. The simple fact of the matter is that once in a series of functional transforms, it's easiest to stay there, which shouldn't be a surprise to anyone given the patterns common usage. That it may affect the purity of Swift's error handling idiom is unfortunate but was anticipated by the Error Handling manifesto itself.

> [@John\_McCall](#):
>
> My opinion is that any feature which combines multiple kinds of propagation in an expression is bound to have confusing interactions, so it's better to "canonicalize" to a single kind of propagation, which probably ought to be error-throwing because it composes more naturally. And the counter-argument was that it _doesn't_ compose more naturally because chaining `flatMap` -like transforms is better than just being able to use the value directly as an expression operand.

I think previous community experience here shows this to be a non-issue. For years users have had little trouble converting between throwing and non-throwing contexts, whether using `Result` or not.

> [@xwu](#):
>
> That is not how I read the decision note. My reading is that the core team was undecided as to whether adding such a transform would be acceptable _under any name_ , not that they were undecided _as to what name_ . Otherwise, the caveat at the end of their decision ("especially as there are alternative means of expressing this using the catching initializer") would be meaningless:
> 
> ![](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/john_mccall/40/1351_2.png) John\_McCall:
> 
> > We spent quite some time debating whether a different name would be acceptable, such as `flatMapThrowing` , but were unable to reach consensus on this, especially as there are alternative means of expressing this using the catching initializer.

That's a bit of a strange interpretation. Given the earlier context not shown here, it's clear to me the core team felt that overloading `flatMap` was unacceptable and searched for another name that could fit. Not finding one, and feeling that the throwing initializer was enough (which I disagree with), they removed it from the proposal.

In any event, the intent of this thread was not to relitigate the existence of a throwing transform at all but to merely explore possible alternate names for such a function. We can argue about its existence if I feel like we've found a good name an create a real pitch / proposal for it.

---

<div class="post-metadata">

**Author:** ![Jon\_Shier](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jon_shier/32/921_2.png) [@Jon\_Shier](https://forums.swift.org/u/Jon_Shier)\
**Post date:** [March 18, 2019, 9:35pm UTC](https://forums.swift.org/t/bikeshedding-supporting-throwing-transforms-on-result/21698/17 "2019-03-18T21:35:41Z")

</div>

I do wonder if an overload with the same name but completely different closure type, whether throwing or not, would run afoul of the core team's desire not to overload based on whether a closure is throwing.

```swift
func flatMap<NewSuccess>(_ transform: (Success) -> Result<NewSuccess, Failure>) -> Result<NewSuccess, Failure>

```

vs.

```swift
func flatMap<NewSuccess>(_ transform: (Success) throws -> NewSuccess) -> Result<NewSuccess, Failure>

```

Of course, this would also have to deal with the possibility of going from a specific `Failure` type to `Error` if the transform fails, but it seems like this isn't a true overload based on throwing vs. not, but instead a rather different type signature altogether.

---

<div class="post-metadata">

**Author:** ![John\_McCall](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/john_mccall/32/1351_2.png) [@John\_McCall](https://forums.swift.org/u/John_McCall)\
**Post date:** [March 18, 2019, 9:51pm UTC](https://forums.swift.org/t/bikeshedding-supporting-throwing-transforms-on-result/21698/18 "2019-03-18T21:51:41Z")

</div>

> [@Jon\_Shier](#):
>
> That's a bit of a strange interpretation. Given the earlier context not shown here, it's clear to me the core team felt that overloading `flatMap` was unacceptable and searched for another name that could fit. Not finding one, and feeling that the throwing initializer was enough (which I disagree with), they removed it from the proposal.

Xiaodi's interpretation is correct. There were three possible positions: (1) we should add throwing-closure transforms as overloads, (2) we should add throwing-closure transforms with a different name, or (3) we should not add throwing-closure transforms. The core team rejected (1) but didn't reach a consensus between (2) and (3), so the easy resolution was to wait and let the community decide how much it mattered, since APIs can always be added later.

I am in camp (3).

---

<div class="post-metadata">

**Author:** ![lukasa](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/lukasa/32/1232_2.png) [@lukasa](https://forums.swift.org/u/lukasa)\
**Post date:** [March 19, 2019, 9:53am UTC](https://forums.swift.org/t/bikeshedding-supporting-throwing-transforms-on-result/21698/19 "2019-03-19T09:53:32Z")

</div>

This proposal tends to encounter issues with the type checker. In particular, if you have a closure that both returns a `Result` and `throws`, the compiler errors are utterly indecipherable.

---

<div class="post-metadata">

**Author:** ![bzamayo](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/bzamayo/32/764_2.png) [@bzamayo](https://forums.swift.org/u/bzamayo)\
**Post date:** [March 19, 2019, 10:39am UTC](https://forums.swift.org/t/bikeshedding-supporting-throwing-transforms-on-result/21698/20 "2019-03-19T10:39:22Z")

</div>

With a method signature:

```swift
public func flatMap<NewSuccess>(_ transform: (Success) throws -> NewSuccess) -> Result<NewSuccess, Error>

```

I don't think there is any overload ambiguity here?

[Next page](https://forums.swift.org/t/bikeshedding-supporting-throwing-transforms-on-result/21698.md?page=2)
