[Accepted and Focused Re-review] SE-0187: Introduce Sequence.filterMap(_:)

My opinion is that filterMap is the right choice of name.

I'm completely biased, given that I already have a Swift library that uses filterMap, in exactly this context, for a Reactive Programming library:

  https://github.com/mattgallagher/CwlSignal/blob/22f1d47895896d7b55bc59a4ee5394071f3c84cf/Sources/CwlSignal/CwlSignalReactive.swift#L453?ts=3

Obviously, I went through the thought process, looked at other libraries and thought it was the best name.

On the topic of a method that "compacts" without also mapping... I think this encourages poor designs that should be using lazy transformations instead of aggregate processing. There is almost always a way around a bare flatten. The obvious quirkiness of `filterMap { $0 }` (or whatever the name ends up being) should be seen as a nudge to re-think the algorithm leading up to that point.

Cheers,
Matt Gallagher.

I can hear the argument, but it errs in the side of premature optimization. Besides, seq.lazy.compacted() still has a meaning.

Gwendal

···

Le 16 nov. 2017 à 06:29, Matt Gallagher via swift-evolution <swift-evolution@swift.org> a écrit :

On the topic of a method that "compacts" without also mapping... I think this encourages poor designs that should be using lazy transformations instead of aggregate processing. There is almost always a way around a bare flatten. The obvious quirkiness of `filterMap { $0 }` (or whatever the name ends up being) should be seen as a nudge to re-think the algorithm leading up to that point.

Another popular Reactive Programming Library uses filterMap with a different signature, and a different meaning: https://github.com/RxSwiftCommunity/RxSwiftExt/blob/3.0.0/Source/RxSwift/filterMap.swift#L32

There are already different interpretations on "filter" in "filterMap" in the wild.

Gwendal Roué

···

Le 16 nov. 2017 à 06:29, Matt Gallagher via swift-evolution <swift-evolution@swift.org> a écrit :

My opinion is that filterMap is the right choice of name.

I'm completely biased, given that I already have a Swift library that uses filterMap, in exactly this context, for a Reactive Programming library:

  https://github.com/mattgallagher/CwlSignal/blob/22f1d47895896d7b55bc59a4ee5394071f3c84cf/Sources/CwlSignal/CwlSignalReactive.swift#L453?ts=3 <https://github.com/mattgallagher/CwlSignal/blob/22f1d47895896d7b55bc59a4ee5394071f3c84cf/Sources/CwlSignal/CwlSignalReactive.swift#L453?ts=3>

mapSome is easy to misunderstand; the naïve reading suggests that only some of the source elements will be mapped, and doesn’t specify which ones. Even if the reader correctly intuits that it refers to Optional.some, they may incorrectly believe that it only maps the non-nil elements in the source sequence. I don’t think this is the right solution.

mapAndUnwrap is accurate to the behavior, but gives an ambiguous impression of what will happen to the nil values. I would worry that returning nil would cause a crash due to a force-unwrap. I don’t want the nil values unwrapped; I want them dropped from the result entirely, so calling it “unwrap” feels scary.

I really think we need something that mentions that the purpose of using this operation is to drop empty values.

-BJ

···

On Nov 16, 2017, at 8:40 AM, Shawn Erickson via swift-evolution <swift-evolution@swift.org> wrote:

I so far am most in favor of mapSome out of the names I have seen followed by mapAndUnwrap (however the later is growing on me).

To me the most important thing is when reading code that it is quick to understand generally what is going on followed by discoverability of a new comer. I think both of these are fairly clear on a quick read while a lot of the others are heavily overloaded terms. I also they sufficiently discoverable / learnable ... also mor so then some of the other overload terms.

-Shawn

On Wed, Nov 15, 2017 at 10:07 PM Gwendal Roué via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Le 16 nov. 2017 à 06:29, Matt Gallagher via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> a écrit :

My opinion is that filterMap is the right choice of name.

I'm completely biased, given that I already have a Swift library that uses filterMap, in exactly this context, for a Reactive Programming library:

  https://github.com/mattgallagher/CwlSignal/blob/22f1d47895896d7b55bc59a4ee5394071f3c84cf/Sources/CwlSignal/CwlSignalReactive.swift#L453?ts=3 <https://github.com/mattgallagher/CwlSignal/blob/22f1d47895896d7b55bc59a4ee5394071f3c84cf/Sources/CwlSignal/CwlSignalReactive.swift#L453?ts=3>

Another popular Reactive Programming Library uses filterMap with a different signature, and a different meaning: https://github.com/RxSwiftCommunity/RxSwiftExt/blob/3.0.0/Source/RxSwift/filterMap.swift#L32

There are already different interpretations on "filter" in "filterMap" in the wild.

Gwendal Roué

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto: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

I disagree that you have to view Optionals as Booleans to understand filterMap as proposed. Optionals naturally represent the idea of either a value, or nothing. The filterMap operation runs a map that can filter stuff out. If you filter something out, you end up with “nothing”, which is exactly what returning nil means. So when I use filterMap, I map all the things I want to let through, and I filter the rest out by letting nothing through.

-BJ

···

On Nov 16, 2017, at 2:52 AM, Gwendal Roué via swift-evolution <swift-evolution@swift.org> wrote:

The optional itself will stand for the boolean needed by the filtering operation.

What I meant here is that "filterMap" can only click in a developer's mind if the the developer uses Optional as a Bool. When the closure returns nil, that nil stands for false in the filtering operation. When the closure returns a `some`, that some stands for true in the filtering operation.

Put in another way: to properly explain "filterMap" to someone who already knows "filter", then you have to explain that optionals are used as booleans.

This library is using filterMap in exactly the same way proposed, except that they use a custom result type instead of Optional. So yes, it has a different signature, but I don’t think it has a different meaning. It’s still running a map operation that may filter some values out.

-BJ

···

On Nov 15, 2017, at 11:07 PM, Gwendal Roué via swift-evolution <swift-evolution@swift.org> wrote:

Le 16 nov. 2017 à 06:29, Matt Gallagher via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> a écrit :

My opinion is that filterMap is the right choice of name.

I'm completely biased, given that I already have a Swift library that uses filterMap, in exactly this context, for a Reactive Programming library:

  https://github.com/mattgallagher/CwlSignal/blob/22f1d47895896d7b55bc59a4ee5394071f3c84cf/Sources/CwlSignal/CwlSignalReactive.swift#L453?ts=3 <https://github.com/mattgallagher/CwlSignal/blob/22f1d47895896d7b55bc59a4ee5394071f3c84cf/Sources/CwlSignal/CwlSignalReactive.swift#L453?ts=3>

Another popular Reactive Programming Library uses filterMap with a different signature, and a different meaning: https://github.com/RxSwiftCommunity/RxSwiftExt/blob/3.0.0/Source/RxSwift/filterMap.swift#L32

There are already different interpretations on "filter" in "filterMap" in the wild.

Gwendal Roué

Yes, you are right. I was too fast.

I've been thinking why filterMap has such a traction in the community, despite the fact that this precise "filter" is a tiny subset of the "filter" generally used by the language.

I think "filterMap" clicks well in many readers because of this trend of thought:

1. I need to transform some values and only keep some of them. But I don't want to use `seq.filter { ... }.map { ... }` or `seq.map { ... }.filter { ... }`. I don't even want to think about the ordering of the filter and mapping operations: that's not interesting. I want a versatile filter+map operation that I'll call "filterMap".
2. Now I need a closure that returns a two-state value: either (in+value), or (out).
3. Which existing Swift type fits such a requirement? Optional, of course. The optional itself will stand for the boolean needed by the filtering operation. The wrapped value will give the mapped value. Pretty efficient.

This trend of thought starts from an actual need (I don't know how to call it) and builds a rationale for it to use the words "filter", "map", and the Optional type. It uses optionals as booleans, which is a venial sin. It happens to build a 100% compatible replacement for the old "flatMap".

The "compact" trend of thought introduces a new operation which filter out nils. It happens to build a 100% compatible replacement for the old "flatMap".

The previous trend of thought (flatMap) did consider optionals as collections. It happens to confuse people, and has been rejected.

The three ways of thinking build the same function. I've been pushing "compact" has a way to better explore the subject. But I really don't know how the Swift community prefers to wire the developer's brains.

Gwendal

···

Le 16 nov. 2017 à 09:12, Anders Ha <anders@andersha.com> a écrit :

It does not use `Optional`, but it is semantically equivalent to `filterMap` in CwlSignal and ReactiveSwift, and the `filterMap` proposed for `Sequence` (but in the time domain instead).

Regards,
Anders

On 16 Nov 2017, at 2:07 PM, Gwendal Roué via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Le 16 nov. 2017 à 06:29, Matt Gallagher via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> a écrit :

My opinion is that filterMap is the right choice of name.

I'm completely biased, given that I already have a Swift library that uses filterMap, in exactly this context, for a Reactive Programming library:

  https://github.com/mattgallagher/CwlSignal/blob/22f1d47895896d7b55bc59a4ee5394071f3c84cf/Sources/CwlSignal/CwlSignalReactive.swift#L453?ts=3 <https://github.com/mattgallagher/CwlSignal/blob/22f1d47895896d7b55bc59a4ee5394071f3c84cf/Sources/CwlSignal/CwlSignalReactive.swift#L453?ts=3>

Another popular Reactive Programming Library uses filterMap with a different signature, and a different meaning: https://github.com/RxSwiftCommunity/RxSwiftExt/blob/3.0.0/Source/RxSwift/filterMap.swift#L32

There are already different interpretations on "filter" in "filterMap" in the wild.

Gwendal Roué

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

The optional itself will stand for the boolean needed by the filtering operation.

What I meant here is that "filterMap" can only click in a developer's mind if the the developer uses Optional as a Bool. When the closure returns nil, that nil stands for false in the filtering operation. When the closure returns a `some`, that some stands for true in the filtering operation.

Put in another way: to properly explain "filterMap" to someone who already knows "filter", then you have to explain that optionals are used as booleans.

Now if one has to answer the canonical question "Does this proposal fit well with the feel and direction of Swift?", then one has to admit that the confusion of Optional with Bool has been rejected a long time ago as not fitting well with the direction of Swift.

Gwendal

I so far am most in favor of mapSome out of the names I have seen followed
by mapAndUnwrap (however the later is growing on me).

To me the most important thing is when reading code that it is quick to
understand generally what is going on followed by discoverability of a new
comer. I think both of these are fairly clear on a quick read while a lot
of the others are heavily overloaded terms. I also they sufficiently
discoverable / learnable ... also mor so then some of the other overload
terms.

-Shawn

···

On Wed, Nov 15, 2017 at 10:07 PM Gwendal Roué via swift-evolution < swift-evolution@swift.org> wrote:

Le 16 nov. 2017 à 06:29, Matt Gallagher via swift-evolution < > swift-evolution@swift.org> a écrit :

My opinion is that filterMap is the right choice of name.

I'm completely biased, given that I already have a Swift library that uses
filterMap, in exactly this context, for a Reactive Programming library:

https://github.com/mattgallagher/CwlSignal/blob/22f1d47895896d7b55bc59a4ee5394071f3c84cf/Sources/CwlSignal/CwlSignalReactive.swift#L453?ts=3

Another popular Reactive Programming Library uses filterMap with a
different signature, and a different meaning:
https://github.com/RxSwiftCommunity/RxSwiftExt/blob/3.0.0/Source/RxSwift/filterMap.swift#L32

There are already different interpretations on "filter" in "filterMap" in
the wild.

Gwendal Roué

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

It does not use `Optional`, but it is semantically equivalent to `filterMap` in CwlSignal and ReactiveSwift, and the `filterMap` proposed for `Sequence` (but in the time domain instead).

Regards,
Anders

···

On 16 Nov 2017, at 2:07 PM, Gwendal Roué via swift-evolution <swift-evolution@swift.org> wrote:

Le 16 nov. 2017 à 06:29, Matt Gallagher via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> a écrit :

My opinion is that filterMap is the right choice of name.

I'm completely biased, given that I already have a Swift library that uses filterMap, in exactly this context, for a Reactive Programming library:

  https://github.com/mattgallagher/CwlSignal/blob/22f1d47895896d7b55bc59a4ee5394071f3c84cf/Sources/CwlSignal/CwlSignalReactive.swift#L453?ts=3 <https://github.com/mattgallagher/CwlSignal/blob/22f1d47895896d7b55bc59a4ee5394071f3c84cf/Sources/CwlSignal/CwlSignalReactive.swift#L453?ts=3>

Another popular Reactive Programming Library uses filterMap with a different signature, and a different meaning: https://github.com/RxSwiftCommunity/RxSwiftExt/blob/3.0.0/Source/RxSwift/filterMap.swift#L32

There are already different interpretations on "filter" in "filterMap" in the wild.

Gwendal Roué

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

So if map can filter, what’s your opinion on calling the operation mapmap? :wink:

···

Am 16.11.2017 um 17:02 schrieb BJ Homer via swift-evolution <swift-evolution@swift.org>:

The filterMap operation runs a map that can filter stuff out.