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

Hello, Swift Community!

The initial review of "SE-0187: Introduce Sequence.filterMap(_:)" ran through yesterday, November 14th, 2017. The proposal is available here:

There was a significant amount of discussion, and people came down with reasonable arguments both for and against the proposal. After reviewing that feedback, the core team feels that the central question is whether Swift benefits from overloading flatMap in this way. There is a reasonable argument that an Optional is a sort of container, and therefore it makes sense to "flatten" that container into a surrounding container. But Swift has resisted applying that interpretation in its library design; for example, you cannot directly iterate an Optional or append its contents to an Array. In general, we feel that using different operations for working with Optionals tends to make code easier to both write and understand, especially given the existence of implicit optional promotion, which we cannot eliminate or easily suppress based on the context. On reflection, we think it was a mistake to use the same name in the first place, and there is no better time to fix a mistake than now.

While we accept that this will cause some amount of "code churn" for developers when they adopt Swift 5, the required change is a simple rename that should be painless to automatically migrate. Of course, sample code on the internet will become obsolete, but fix-its will easily update that code if pasted into a project, and the samples themselves (once corrected) should become clearer and easier to teach after this change, as is generally true when overloading is removed.

Accordingly, SE-0187 is accepted, at least as far as not calling the operation "flatMap". We are re-opening the review until next Monday, November 20th, 2017, in order to have a focused discussion about the new name. Names that seemed to gain some traction in the first review include:

  - filterMap, which has precedent in existing functional languages, as well as some popular Swift libraries, but which some people view as confusing

  - compactMap, which builds off the precedent of "compact" in Ruby

But please feel free to suggest a name other than these.

Reviews

Reviews are an important part of the Swift evolution process. All reviews should be sent to the swift-evolution mailing list at

https://lists.swift.org/mailman/listinfo/swift-evolution
or, if you would like to keep your feedback private, directly to me as the review manager. When replying, please try to keep the proposal link at the top of the message:

Proposal link:

Reply text
Other replies
What goes into a review?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift.

When writing your review, here are some questions you might want to answer in your review:

  • What is your evaluation of the proposal?
  • Is the problem being addressed significant enough to warrant a change to Swift?
  • Does this proposal fit well with the feel and direction of Swift?
  • If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

More information about the Swift evolution process is available at:

As always, thank you for contributing to the evolution of Swift.

John McCall
Review Manager

I continue to favour mapSome, since it’s both literally and figuratively what it does, but appreciate that exposing the name of the Optional.some case isn’t to everyone’s taste.

···

On Nov 15, 2017, at 12:55 PM, John McCall via swift-evolution <swift-evolution@swift.org> wrote:

Hello, Swift Community!

The initial review of "SE-0187: Introduce Sequence.filterMap(_:)" ran through yesterday, November 14th, 2017. The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.md

There was a significant amount of discussion, and people came down with reasonable arguments both for and against the proposal. After reviewing that feedback, the core team feels that the central question is whether Swift benefits from overloading flatMap in this way. There is a reasonable argument that an Optional is a sort of container, and therefore it makes sense to "flatten" that container into a surrounding container. But Swift has resisted applying that interpretation in its library design; for example, you cannot directly iterate an Optional or append its contents to an Array. In general, we feel that using different operations for working with Optionals tends to make code easier to both write and understand, especially given the existence of implicit optional promotion, which we cannot eliminate or easily suppress based on the context. On reflection, we think it was a mistake to use the same name in the first place, and there is no better time to fix a mistake than now.

While we accept that this will cause some amount of "code churn" for developers when they adopt Swift 5, the required change is a simple rename that should be painless to automatically migrate. Of course, sample code on the internet will become obsolete, but fix-its will easily update that code if pasted into a project, and the samples themselves (once corrected) should become clearer and easier to teach after this change, as is generally true when overloading is removed.

Accordingly, SE-0187 is accepted, at least as far as not calling the operation "flatMap". We are re-opening the review until next Monday, November 20th, 2017, in order to have a focused discussion about the new name. Names that seemed to gain some traction in the first review include:

  - filterMap, which has precedent in existing functional languages, as well as some popular Swift libraries, but which some people view as confusing

  - compactMap, which builds off the precedent of "compact" in Ruby

But please feel free to suggest a name other than these.

Reviews

Reviews are an important part of the Swift evolution process. All reviews should be sent to the swift-evolution mailing list at

https://lists.swift.org/mailman/listinfo/swift-evolution
or, if you would like to keep your feedback private, directly to me as the review manager. When replying, please try to keep the proposal link at the top of the message:

Proposal link:

https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.md
Reply text
Other replies
What goes into a review?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift.

When writing your review, here are some questions you might want to answer in your review:

  • What is your evaluation of the proposal?
  • Is the problem being addressed significant enough to warrant a change to Swift?
  • Does this proposal fit well with the feel and direction of Swift?
  • If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

More information about the Swift evolution process is available at:

https://github.com/apple/swift-evolution/blob/master/process.md

As always, thank you for contributing to the evolution of Swift.

John McCall
Review Manager
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

On Wed, Nov 15, 2017, at 12:55 PM, John McCall via swift-evolution wrote:> Hello, Swift Community!

The initial review of "SE-0187: Introduce Sequence.filterMap(_:)"
ran through yesterday, November 14th, 2017. The proposal is
available here:>

https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.md&gt;

There was a significant amount of discussion, and people came down
with reasonable arguments both for and against the proposal. After
reviewing that feedback, the core team feels that the central question
is whether Swift benefits from overloading flatMap in this way. There
is a reasonable argument that an Optional is a sort of container, and
therefore it makes sense to "flatten" that container into a
surrounding container. But Swift has resisted applying that
interpretation in its library design; for example, you cannot directly
iterate an Optional or append its contents to an Array. In general,
we feel that using different operations for working with Optionals
tends to make code easier to both write and understand, especially
given the existence of implicit optional promotion, which we cannot
eliminate or easily suppress based on the context. On reflection, we
think it was a mistake to use the same name in the first place, and
there is no better time to fix a mistake than now.>
While we accept that this will cause some amount of "code churn" for
developers when they adopt Swift 5, the required change is a simple
rename that should be painless to automatically migrate. Of course,
sample code on the internet will become obsolete, but fix-its will
easily update that code if pasted into a project, and the samples
themselves (once corrected) should become clearer and easier to teach
after this change, as is generally true when overloading is removed.>
Accordingly, SE-0187 is *accepted*, at least as far as not calling the
operation "flatMap". We are re-opening the review until next Monday,
November 20th, 2017, in order to have a focused discussion about the
new name. Names that seemed to gain some traction in the first review
include:>
  - filterMap, which has precedent in existing functional languages,
    as well as some popular Swift libraries, but which some people
    view as confusing>
  - compactMap, which builds off the precedent of "compact" in Ruby

But please feel free to suggest a name other than these.

*Reviews*

Reviews are an important part of the Swift evolution process. All
reviews should be sent to the swift-evolution mailing list at>

https://lists.swift.org/mailman/listinfo/swift-evolution

or, if you would like to keep your feedback private, directly to me as
the review manager. When replying, please try to keep the proposal
link at the top of the message:>

Proposal link:

https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.md&gt;&gt; Reply text
Other replies

*What goes into a review?*

The goal of the review process is to improve the proposal under review
through constructive criticism and, eventually, determine the
direction of Swift.>
When writing your review, here are some questions you might want to
answer in your review:>
• What is your evaluation of the proposal?

I'm not happy about the method being renamed, but if it must, I'm in
favor of filterMap. All the other suggestions I've seen are either weird
(e.g. "compact", which has no precedent in Swift or anything else I can
think of beyond Ruby), or potentially misleading (like mapSome, which
sounds like it takes a sequence of optionals and only modifies the non-
nil values).
-Kevin Ballard

···

• Is the problem being addressed significant enough to warrant a
change to Swift?> • Does this proposal fit well with the feel and direction of Swift?
• If you have used other languages or libraries with a similar
feature, how do you feel that this proposal compares to those?> • How much effort did you put into your review? A glance, a quick
reading, or an in-depth study?>
More information about the Swift evolution process is available at:

https://github.com/apple/swift-evolution/blob/master/process.md

As always, thank you for contributing to the evolution of Swift.

John McCall
Review Manager
_________________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

I'd like to show my support for mapSome. It's clear, concise and to the point. It's the best name from all the alternatives IMHO

···

On Nov 15, 2017, at 7:15 PM, Ben Cohen via swift-evolution <swift-evolution@swift.org> wrote:

I continue to favour mapSome, since it’s both literally and figuratively what it does, but appreciate that exposing the name of the Optional.some case isn’t to everyone’s taste.

On Nov 15, 2017, at 12:55 PM, John McCall via swift-evolution <swift-evolution@swift.org> wrote:

Hello, Swift Community!

The initial review of "SE-0187: Introduce Sequence.filterMap(_:)" ran through yesterday, November 14th, 2017. The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.md

There was a significant amount of discussion, and people came down with reasonable arguments both for and against the proposal. After reviewing that feedback, the core team feels that the central question is whether Swift benefits from overloading flatMap in this way. There is a reasonable argument that an Optional is a sort of container, and therefore it makes sense to "flatten" that container into a surrounding container. But Swift has resisted applying that interpretation in its library design; for example, you cannot directly iterate an Optional or append its contents to an Array. In general, we feel that using different operations for working with Optionals tends to make code easier to both write and understand, especially given the existence of implicit optional promotion, which we cannot eliminate or easily suppress based on the context. On reflection, we think it was a mistake to use the same name in the first place, and there is no better time to fix a mistake than now.

While we accept that this will cause some amount of "code churn" for developers when they adopt Swift 5, the required change is a simple rename that should be painless to automatically migrate. Of course, sample code on the internet will become obsolete, but fix-its will easily update that code if pasted into a project, and the samples themselves (once corrected) should become clearer and easier to teach after this change, as is generally true when overloading is removed.

Accordingly, SE-0187 is accepted, at least as far as not calling the operation "flatMap". We are re-opening the review until next Monday, November 20th, 2017, in order to have a focused discussion about the new name. Names that seemed to gain some traction in the first review include:

  - filterMap, which has precedent in existing functional languages, as well as some popular Swift libraries, but which some people view as confusing

  - compactMap, which builds off the precedent of "compact" in Ruby

But please feel free to suggest a name other than these.

Reviews

Reviews are an important part of the Swift evolution process. All reviews should be sent to the swift-evolution mailing list at

https://lists.swift.org/mailman/listinfo/swift-evolution

or, if you would like to keep your feedback private, directly to me as the review manager. When replying, please try to keep the proposal link at the top of the message:

Proposal link:

https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.md
Reply text
Other replies
What goes into a review?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift.

When writing your review, here are some questions you might want to answer in your review:

  • What is your evaluation of the proposal?
  • Is the problem being addressed significant enough to warrant a change to Swift?
  • Does this proposal fit well with the feel and direction of Swift?
  • If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

More information about the Swift evolution process is available at:

https://github.com/apple/swift-evolution/blob/master/process.md

As always, thank you for contributing to the evolution of Swift.

John McCall
Review Manager
_______________________________________________
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

Hello, Swift Community!

The initial review of "SE-0187: Introduce Sequence.filterMap(_:)" ran through yesterday, November 14th, 2017. The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.md

There was a significant amount of discussion, and people came down with reasonable arguments both for and against the proposal. After reviewing that feedback, the core team feels that the central question is whether Swift benefits from overloading flatMap in this way. There is a reasonable argument that an Optional is a sort of container, and therefore it makes sense to "flatten" that container into a surrounding container. But Swift has resisted applying that interpretation in its library design; for example, you cannot directly iterate an Optional or append its contents to an Array. In general, we feel that using different operations for working with Optionals tends to make code easier to both write and understand, especially given the existence of implicit optional promotion, which we cannot eliminate or easily suppress based on the context. On reflection, we think it was a mistake to use the same name in the first place, and there is no better time to fix a mistake than now.

While we accept that this will cause some amount of "code churn" for developers when they adopt Swift 5, the required change is a simple rename that should be painless to automatically migrate. Of course, sample code on the internet will become obsolete, but fix-its will easily update that code if pasted into a project, and the samples themselves (once corrected) should become clearer and easier to teach after this change, as is generally true when overloading is removed.

Accordingly, SE-0187 is accepted, at least as far as not calling the operation "flatMap". We are re-opening the review until next Monday, November 20th, 2017, in order to have a focused discussion about the new name. Names that seemed to gain some traction in the first review include:

  - filterMap, which has precedent in existing functional languages, as well as some popular Swift libraries, but which some people view as confusing

  - compactMap, which builds off the precedent of "compact" in Ruby

But please feel free to suggest a name other than these.

Reviews

Reviews are an important part of the Swift evolution process. All reviews should be sent to the swift-evolution mailing list at

https://lists.swift.org/mailman/listinfo/swift-evolution
or, if you would like to keep your feedback private, directly to me as the review manager. When replying, please try to keep the proposal link at the top of the message:

Proposal link:

https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.md
Reply text
Other replies
What goes into a review?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift.

When writing your review, here are some questions you might want to answer in your review:

  • What is your evaluation of the proposal?

I’m happy that the rename was accepted. I’d like to support renaming it to filterMap because it uses two terms of art already pre-existing and understood by the Swift community: map makes it clear it is an operation on a Sequence, while filter makes it clear that the resulting array may be smaller than original array.

I’m very much against a term like compactMap because it uses the term compact which has no precedence in Swift’s Standard Library.

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

Yes.

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

Yes.

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

Yes, but I think that comparing with other languages (like Ruby for compactMap) is not the right approach. We need to choose a name which feels at home in the Standard Library.

···

On 15 Nov 2017, at 21:55, John McCall via swift-evolution <swift-evolution@swift.org> wrote:

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

More information about the Swift evolution process is available at:

https://github.com/apple/swift-evolution/blob/master/process.md

As always, thank you for contributing to the evolution of Swift.

John McCall
Review Manager
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

I understand the sentiment, but the language has so much sugar over Optional that I wouldn’t be surprised if even seasoned developers didn't know the name of Optional’s cases.

···

On 15 Nov 2017, at 22:15, Ben Cohen via swift-evolution <swift-evolution@swift.org> wrote:

I continue to favour mapSome, since it’s both literally and figuratively what it does, but appreciate that exposing the name of the Optional.some case isn’t to everyone’s taste.

On Nov 15, 2017, at 12:55 PM, John McCall via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hello, Swift Community!

The initial review of "SE-0187: Introduce Sequence.filterMap(_:)" ran through yesterday, November 14th, 2017. The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.md

There was a significant amount of discussion, and people came down with reasonable arguments both for and against the proposal. After reviewing that feedback, the core team feels that the central question is whether Swift benefits from overloading flatMap in this way. There is a reasonable argument that an Optional is a sort of container, and therefore it makes sense to "flatten" that container into a surrounding container. But Swift has resisted applying that interpretation in its library design; for example, you cannot directly iterate an Optional or append its contents to an Array. In general, we feel that using different operations for working with Optionals tends to make code easier to both write and understand, especially given the existence of implicit optional promotion, which we cannot eliminate or easily suppress based on the context. On reflection, we think it was a mistake to use the same name in the first place, and there is no better time to fix a mistake than now.

While we accept that this will cause some amount of "code churn" for developers when they adopt Swift 5, the required change is a simple rename that should be painless to automatically migrate. Of course, sample code on the internet will become obsolete, but fix-its will easily update that code if pasted into a project, and the samples themselves (once corrected) should become clearer and easier to teach after this change, as is generally true when overloading is removed.

Accordingly, SE-0187 is accepted, at least as far as not calling the operation "flatMap". We are re-opening the review until next Monday, November 20th, 2017, in order to have a focused discussion about the new name. Names that seemed to gain some traction in the first review include:

  - filterMap, which has precedent in existing functional languages, as well as some popular Swift libraries, but which some people view as confusing

  - compactMap, which builds off the precedent of "compact" in Ruby

But please feel free to suggest a name other than these.

Reviews

Reviews are an important part of the Swift evolution process. All reviews should be sent to the swift-evolution mailing list at

https://lists.swift.org/mailman/listinfo/swift-evolution
or, if you would like to keep your feedback private, directly to me as the review manager. When replying, please try to keep the proposal link at the top of the message:

Proposal link:

https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.md
Reply text
Other replies
What goes into a review?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift.

When writing your review, here are some questions you might want to answer in your review:

  • What is your evaluation of the proposal?
  • Is the problem being addressed significant enough to warrant a change to Swift?
  • Does this proposal fit well with the feel and direction of Swift?
  • If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

More information about the Swift evolution process is available at:

https://github.com/apple/swift-evolution/blob/master/process.md

As always, thank you for contributing to the evolution of Swift.

John McCall
Review Manager
_______________________________________________
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

Hello,

I cast my vote for compactMap. And I wish for another proposal for the plain non-mutating method `compacted`.

Some say that compact has no precedent in Swift, and is ambiguous.

"Compact" has no precedent because it names an operation which had no name yet: filtering out nils. Is is only as ambiguous as one resists mapping "compact" to "filter out nils".

Suggesting "compact" is suggesting that we acknowledge that filtering out nils is a very common operation which deserves its own name. Hence the wish for `array.compacted()` as a shorthand for `array.compactMap { $0 }`.

Suggesting "compact" is suggesting that we stop using the functional programming vocabulary for an operation that does not quite fit this model, as functional experts here have reminded several times.

"Compact" is not an attempt at piling up existing Swift words until they build "filtering out nils". That's three words. "Compact" elegantly compacts them all in a single word that is easy to learn, and remember.

"filterMap" forgets about nil checking. To support "filterMap", some claim that "filter" is OK because it means "reduce the size of an array". OK, but we are still missing "nils".

“unwrappingMap”, "mapAndUnwrap", "mapUnwrappingSome", "mapUnwrapSome", "mapUnwrapIfSome", and generally names around "unwrap": those are serious candidates. But what could be the natural shortening for `array.unwrappingMap { $0 }`? `array.unwrapped()`? What does it mean to "unwrap" a collection?

"mapSome" does not do what it claims: it maps, then keeps the some, instead of mapping the some.

"mapNonNil": same as above

"selectiveMap": it would be OK if "selecting" would be defined as "filtering out nils". Yet "compact" is better at this job, because "compacting" already, in English, means compressing by removing voids. "Selecting", in English, is a synonym for "filtering", and is less good as "compact", assuming we acknowledge introducing a new word in the Swift vocabulary for the "filtering out nils" operation.

“mapDroppingNil”, "mapStrippingNil" : now it's a matter of taste :-)

Gwendal Roué
Sorry for the not-so-compact reply

···

Le 15 nov. 2017 à 21:55, John McCall via swift-evolution <swift-evolution@swift.org> a écrit :

Hello, Swift Community!

The initial review of "SE-0187: Introduce Sequence.filterMap(_:)" ran through yesterday, November 14th, 2017. The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.md

There was a significant amount of discussion, and people came down with reasonable arguments both for and against the proposal. After reviewing that feedback, the core team feels that the central question is whether Swift benefits from overloading flatMap in this way. There is a reasonable argument that an Optional is a sort of container, and therefore it makes sense to "flatten" that container into a surrounding container. But Swift has resisted applying that interpretation in its library design; for example, you cannot directly iterate an Optional or append its contents to an Array. In general, we feel that using different operations for working with Optionals tends to make code easier to both write and understand, especially given the existence of implicit optional promotion, which we cannot eliminate or easily suppress based on the context. On reflection, we think it was a mistake to use the same name in the first place, and there is no better time to fix a mistake than now.

While we accept that this will cause some amount of "code churn" for developers when they adopt Swift 5, the required change is a simple rename that should be painless to automatically migrate. Of course, sample code on the internet will become obsolete, but fix-its will easily update that code if pasted into a project, and the samples themselves (once corrected) should become clearer and easier to teach after this change, as is generally true when overloading is removed.

Accordingly, SE-0187 is accepted, at least as far as not calling the operation "flatMap". We are re-opening the review until next Monday, November 20th, 2017, in order to have a focused discussion about the new name. Names that seemed to gain some traction in the first review include:

  - filterMap, which has precedent in existing functional languages, as well as some popular Swift libraries, but which some people view as confusing

  - compactMap, which builds off the precedent of "compact" in Ruby

But please feel free to suggest a name other than these.

Reviews

Reviews are an important part of the Swift evolution process. All reviews should be sent to the swift-evolution mailing list at

https://lists.swift.org/mailman/listinfo/swift-evolution

or, if you would like to keep your feedback private, directly to me as the review manager. When replying, please try to keep the proposal link at the top of the message:

Proposal link:

https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.md
Reply text
Other replies
What goes into a review?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift.

When writing your review, here are some questions you might want to answer in your review:

  • What is your evaluation of the proposal?
  • Is the problem being addressed significant enough to warrant a change to Swift?
  • Does this proposal fit well with the feel and direction of Swift?
  • If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

More information about the Swift evolution process is available at:

https://github.com/apple/swift-evolution/blob/master/process.md

As always, thank you for contributing to the evolution of Swift.

John McCall
Review Manager
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

I like `mapSome`:

* `mapSome` uses conventional Swift terminology.
* It makes the outcome and expectations clear.
* As a bonus, it combines the English meaning of "some" ("map across some of these items", as in creating a filtered result) and the `Optional` case name.

In response to John's "mapSome and especially mapNonNil both sound to me like they only map the non-nil values in the source sequence.", I'd respond that the mode of action is:

1. apply the function
2. retrieve `some` cases

Selecting `mapSome` reflects those two stages. There is, however, Kevin's (sound) point against that it "sounds like it takes a sequence of optionals and only modifies the non-nil values", but I still like it. Some of the suggestions built around unwrapping address John's concern, for example `mapUnwrapped` but fail to distinguish between the `some` and `nil` cases, suggesting perhaps a catastrophic outcome for nil values.

I could live with many of the other names but I dislike `compact` (it has no precedent, sets an expectation of the implementation which may not match reality). Similarly `mapReduce` or `mapReducing` (which I prefer to `reduceMap`) may overburden the expectation of the existing `reduce`, where a user thinks prior results feed into the output, which they don't. I moderately like `mapSelective` (over `selectiveMap`) but I like it less than `filterMap`, `mapFiltering`, or `mapFiltered` and `mapSome`, all of which use Swift terms of art in their naming. (Also note Gwendal's finding that as a term of art, it has "a different signature, and a different meaning" in RxSwift.)

Summary:

* I like `mapSome`
* I'm fine with a `filter` variation, of which I prefer `mapFiltered`

-- E, former supporter of `filterMap` before `mapSome` entered her awareness

···

On Nov 15, 2017, at 2:15 PM, Ben Cohen via swift-evolution <swift-evolution@swift.org> wrote:

I continue to favour mapSome, since it’s both literally and figuratively what it does, but appreciate that exposing the name of the Optional.some case isn’t to everyone’s taste.

On Nov 15, 2017, at 12:55 PM, John McCall via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hello, Swift Community!

The initial review of "SE-0187: Introduce Sequence.filterMap(_:)" ran through yesterday, November 14th, 2017. The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.md

There was a significant amount of discussion, and people came down with reasonable arguments both for and against the proposal. After reviewing that feedback, the core team feels that the central question is whether Swift benefits from overloading flatMap in this way. There is a reasonable argument that an Optional is a sort of container, and therefore it makes sense to "flatten" that container into a surrounding container. But Swift has resisted applying that interpretation in its library design; for example, you cannot directly iterate an Optional or append its contents to an Array. In general, we feel that using different operations for working with Optionals tends to make code easier to both write and understand, especially given the existence of implicit optional promotion, which we cannot eliminate or easily suppress based on the context. On reflection, we think it was a mistake to use the same name in the first place, and there is no better time to fix a mistake than now.

While we accept that this will cause some amount of "code churn" for developers when they adopt Swift 5, the required change is a simple rename that should be painless to automatically migrate. Of course, sample code on the internet will become obsolete, but fix-its will easily update that code if pasted into a project, and the samples themselves (once corrected) should become clearer and easier to teach after this change, as is generally true when overloading is removed.

Accordingly, SE-0187 is accepted, at least as far as not calling the operation "flatMap". We are re-opening the review until next Monday, November 20th, 2017, in order to have a focused discussion about the new name. Names that seemed to gain some traction in the first review include:

  - filterMap, which has precedent in existing functional languages, as well as some popular Swift libraries, but which some people view as confusing

  - compactMap, which builds off the precedent of "compact" in Ruby

But please feel free to suggest a name other than these.

Reviews

Reviews are an important part of the Swift evolution process. All reviews should be sent to the swift-evolution mailing list at

https://lists.swift.org/mailman/listinfo/swift-evolution
or, if you would like to keep your feedback private, directly to me as the review manager. When replying, please try to keep the proposal link at the top of the message:

Proposal link:

https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.md
Reply text
Other replies
What goes into a review?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift.

When writing your review, here are some questions you might want to answer in your review:

  • What is your evaluation of the proposal?
  • Is the problem being addressed significant enough to warrant a change to Swift?
  • Does this proposal fit well with the feel and direction of Swift?
  • If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

More information about the Swift evolution process is available at:

https://github.com/apple/swift-evolution/blob/master/process.md

As always, thank you for contributing to the evolution of Swift.

John McCall
Review Manager
_______________________________________________
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

The typical case for this function in my code is the identity closure, that is

let a: \[Int?\] = \.\.\.
print\(a\.filterMap \{$0\}\)

filterMap is quite poor for this situation because *each* component in the term is inaccurate:

1. While we are filtering in the "english sense", in Swift the word "filter" carries a specific meaning involving booleans. In particular if `a` were of type `[Bool?]` I believe new Swift programmers would fail to predict the result
2. This is not a map operation when used with the identity closure.

Most of the discussion so far addresses 1 but not 2, e.g. mapSome, mapCompact improve dimension 1 but not dimension 2.

I support mapMaybe because from the choices so far it is the only one that seems to address both dimensions.

It can also be argued that the combined API itself is a mistake, e.g. that a distinct API for discarding optionals as from mapping would be superior. But that may be too radical at this point.

···

On November 15, 2017 at 2:55:10 PM, John McCall (rjmccall@apple.com) wrote:

Hello, Swift Community!

The initial review of "SE-0187: Introduce Sequence.filterMap(_:)" ran through yesterday, November 14th, 2017. The proposal is available here:

There was a significant amount of discussion, and people came down with reasonable arguments both for and against the proposal. After reviewing that feedback, the core team feels that the central question is whether Swift benefits from overloading flatMap in this way. There is a reasonable argument that an Optional is a sort of container, and therefore it makes sense to "flatten" that container into a surrounding container. But Swift has resisted applying that interpretation in its library design; for example, you cannot directly iterate an Optional or append its contents to an Array. In general, we feel that using different operations for working with Optionals tends to make code easier to both write and understand, especially given the existence of implicit optional promotion, which we cannot eliminate or easily suppress based on the context. On reflection, we think it was a mistake to use the same name in the first place, and there is no better time to fix a mistake than now.

While we accept that this will cause some amount of "code churn" for developers when they adopt Swift 5, the required change is a simple rename that should be painless to automatically migrate. Of course, sample code on the internet will become obsolete, but fix-its will easily update that code if pasted into a project, and the samples themselves (once corrected) should become clearer and easier to teach after this change, as is generally true when overloading is removed.

Accordingly, SE-0187 is accepted, at least as far as not calling the operation "flatMap". We are re-opening the review until next Monday, November 20th, 2017, in order to have a focused discussion about the new name. Names that seemed to gain some traction in the first review include:

- filterMap, which has precedent in existing functional languages, as well as some popular Swift libraries, but which some people view as confusing

- compactMap, which builds off the precedent of "compact" in Ruby

But please feel free to suggest a name other than these.

Reviews

Reviews are an important part of the Swift evolution process. All reviews should be sent to the swift-evolution mailing list at

https://lists.swift.org/mailman/listinfo/swift-evolution

or, if you would like to keep your feedback private, directly to me as the review manager. When replying, please try to keep the proposal link at the top of the message:

Proposal link:

Reply text
Other replies
What goes into a review?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift.

When writing your review, here are some questions you might want to answer in your review:

• What is your evaluation of the proposal?
• Is the problem being addressed significant enough to warrant a change to Swift?
• Does this proposal fit well with the feel and direction of Swift?
• If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
• How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

More information about the Swift evolution process is available at:

As always, thank you for contributing to the evolution of Swift.

John McCall
Review Manager
_______________________________________________
swift-evolution-announce mailing list
swift-evolution-announce@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution-announce

I don’t really care what the name ends up being (as long as it’s not “flatMap”), but you do bring up something worth addressing.

I imagine a majority of calls to this function are of the lines of “compactMap { $0 }”, so maybe it’s worth adding a helper/alias like “compact()”?

Stephen

···

On Nov 15, 2017, at 4:15 PM, David Hart via swift-evolution <swift-evolution@swift.org> wrote:

I’m very much against a term like compactMap because it uses the term compact which has no precedence in Swift’s Standard Library.

I’m happy that the rename was accepted. I’d like to support renaming it to filterMap because it uses two terms of art already pre-existing and understood by the Swift community

Odd… exactly that is the reason why I think filterMap is the worst choice:
Both are established terms of art, but one has a meaning that doesn’t fit to the operation.
Applying filter can remove elements, but it can never change types (I feel kind of silly to repeat this over and over, but so far, nobody took the time to falsify this).

So, I’d rather introduce a unburnt word than reuse an existing term that conveys a wrong message. Honestly, I’d consider „reduceMap“ less bad… but I can’t see any good reason to limit the choice to something that is already used in Swift — after all, we don’t have to pay for new names.

As far as the Sequence overloads: I really, really think we should go a step beyond renaming and separate the functions into the underlying operations. FlatMap has three separate and orthogonal effects, so it should be split into three functions—flatten, map, and dropNil. Map already exists, obviously, but flatten and dropNil (or compact[ed], as I've seen suggested) are independently useful—I've used `.flatMap { $0 }` several times, and I've written my own `flatten` because I didn't actually realize there was a separate overload for that (I don't want to sound rude to the Apple devs who decided on that, but… why on earth was an already confusing name overloaded with unrelated functionality instead of using the term of art?).

For Optional, I suggest mapValue.

···

On Nov 16, 2017, at 8:11 AM, Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:

I like `mapSome`:

* `mapSome` uses conventional Swift terminology.
* It makes the outcome and expectations clear.
* As a bonus, it combines the English meaning of "some" ("map across some of these items", as in creating a filtered result) and the `Optional` case name.

In response to John's "mapSome and especially mapNonNil both sound to me like they only map the non-nil values in the source sequence.", I'd respond that the mode of action is:

1. apply the function
2. retrieve `some` cases

Selecting `mapSome` reflects those two stages. There is, however, Kevin's (sound) point against that it "sounds like it takes a sequence of optionals and only modifies the non-nil values", but I still like it. Some of the suggestions built around unwrapping address John's concern, for example `mapUnwrapped` but fail to distinguish between the `some` and `nil` cases, suggesting perhaps a catastrophic outcome for nil values.

I could live with many of the other names but I dislike `compact` (it has no precedent, sets an expectation of the implementation which may not match reality). Similarly `mapReduce` or `mapReducing` (which I prefer to `reduceMap`) may overburden the expectation of the existing `reduce`, where a user thinks prior results feed into the output, which they don't. I moderately like `mapSelective` (over `selectiveMap`) but I like it less than `filterMap`, `mapFiltering`, or `mapFiltered` and `mapSome`, all of which use Swift terms of art in their naming. (Also note Gwendal's finding that as a term of art, it has "a different signature, and a different meaning" in RxSwift.)

Summary:

* I like `mapSome`
* I'm fine with a `filter` variation, of which I prefer `mapFiltered`

-- E, former supporter of `filterMap` before `mapSome` entered her awareness

On Nov 15, 2017, at 2:15 PM, Ben Cohen via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I continue to favour mapSome, since it’s both literally and figuratively what it does, but appreciate that exposing the name of the Optional.some case isn’t to everyone’s taste.

On Nov 15, 2017, at 12:55 PM, John McCall via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hello, Swift Community!

The initial review of "SE-0187: Introduce Sequence.filterMap(_:)" ran through yesterday, November 14th, 2017. The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.md

There was a significant amount of discussion, and people came down with reasonable arguments both for and against the proposal. After reviewing that feedback, the core team feels that the central question is whether Swift benefits from overloading flatMap in this way. There is a reasonable argument that an Optional is a sort of container, and therefore it makes sense to "flatten" that container into a surrounding container. But Swift has resisted applying that interpretation in its library design; for example, you cannot directly iterate an Optional or append its contents to an Array. In general, we feel that using different operations for working with Optionals tends to make code easier to both write and understand, especially given the existence of implicit optional promotion, which we cannot eliminate or easily suppress based on the context. On reflection, we think it was a mistake to use the same name in the first place, and there is no better time to fix a mistake than now.

While we accept that this will cause some amount of "code churn" for developers when they adopt Swift 5, the required change is a simple rename that should be painless to automatically migrate. Of course, sample code on the internet will become obsolete, but fix-its will easily update that code if pasted into a project, and the samples themselves (once corrected) should become clearer and easier to teach after this change, as is generally true when overloading is removed.

Accordingly, SE-0187 is accepted, at least as far as not calling the operation "flatMap". We are re-opening the review until next Monday, November 20th, 2017, in order to have a focused discussion about the new name. Names that seemed to gain some traction in the first review include:

  - filterMap, which has precedent in existing functional languages, as well as some popular Swift libraries, but which some people view as confusing

  - compactMap, which builds off the precedent of "compact" in Ruby

But please feel free to suggest a name other than these.

Reviews

Reviews are an important part of the Swift evolution process. All reviews should be sent to the swift-evolution mailing list at

https://lists.swift.org/mailman/listinfo/swift-evolution
or, if you would like to keep your feedback private, directly to me as the review manager. When replying, please try to keep the proposal link at the top of the message:

Proposal link:

https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.md
Reply text
Other replies
What goes into a review?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift.

When writing your review, here are some questions you might want to answer in your review:

  • What is your evaluation of the proposal?
  • Is the problem being addressed significant enough to warrant a change to Swift?
  • Does this proposal fit well with the feel and direction of Swift?
  • If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

More information about the Swift evolution process is available at:

https://github.com/apple/swift-evolution/blob/master/process.md

As always, thank you for contributing to the evolution of Swift.

John McCall
Review Manager
_______________________________________________
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 <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’ll put my vote in for `filterMap`!

I’d like to call out some fun properties and generalizations that
`filterMap` has that might give a little more credence to why it should be
called this.

There is a very natural way of bridging the worlds of optionals and
booleans. In fact, considering that `Bool` is the unique type with two
elements, we could even define `typealias Bool = Void?`, where `Void()` is
true and `nil` is false! Though I am definitely not advocating that!

Given that perspective, there is then also a natural way of lifting
predicates `(A) -> Bool` to the world of functions that `filterMap`
understands:

func optionalBool<A>(_ p: @escaping (A) -> Bool) -> (A) -> A? {
  return { p($0) ? .some($0) : nil }
}

Given such a function, then `filter` on arrays is nothing but
`filterMap(optionalBool(p))`!

The really exciting part is then to take note that the highly contested and
dreaded `Either<A, B>` is just a generalization of `Optional<B>`, in that
we model the absence of `B` by providing a value of type `A`. Given that
observation, what does the filter/filterMap story look like for `Either`s?
Why that’s none other than `partition` and `partitionMap`! These are
functions that allow you to partition an array into two subsets. The first
one doesn’t change the wrapped value of the array (much like `filter`) but
the second allows providing an additional mapping function. Here’s how they
might look:

func _partitionMap<A, B>(_ p: @escaping (Element) -> Either<A, B>) ->
(left: [A], right: [B]) {
  var result = (left: [A](), right: [B]())
  for x in self {
    switch p(x) {
    case let .left(a):
      result.left.append(a)
    case let .right(b):
      result.right.append(b)
    }
  }
  return result
}

func _partition(_ p: @escaping (Element) -> Bool) -> (`true`: Array,
`false`: Array) {
  // Can easily define `_partition` in terms of `_partitionMap`!
  return _partitionMap(eitherBool(p))
}

The things that are nice about this:

* Builds on a few foundational, atomic ideas.
* Shows that there are future generalizations that we might not even be
thinking about right now
* Allows one to see the shadows of simpler constructions (e.g.
filter/partition) from the more complex constructions (e.g.
filterMap/partitionMap)

I will conclude that I 100% am not advocating for us to bring in `Either`
and `optionalBool` and `eitherBool` and all that wildness. I simply want to
show that there are some wonderful ideas lurking behind these names, and so
it’d be nice to not hide them with overly specific and overly descriptive
names.

If anyone wants to play with these functions I have put them in a gist:

···

On Nov 15, 2017, at 12:55 PM, John McCall via swift-evolution < > swift-evolution@swift.org> wrote:

Hello, Swift Community!

The initial review of "SE-0187: Introduce Sequence.filterMap(_:)" ran
through yesterday, November 14th, 2017. The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.md

There was a significant amount of discussion, and people came down with
reasonable arguments both for and against the proposal. After reviewing
that feedback, the core team feels that the central question is whether
Swift benefits from overloading flatMap in this way. There is a reasonable
argument that an Optional is a sort of container, and therefore it makes
sense to "flatten" that container into a surrounding container. But Swift
has resisted applying that interpretation in its library design; for
example, you cannot directly iterate an Optional or append its contents to
an Array. In general, we feel that using different operations for working
with Optionals tends to make code easier to both write and understand,
especially given the existence of implicit optional promotion, which we
cannot eliminate or easily suppress based on the context. On reflection,
we think it was a mistake to use the same name in the first place, and
there is no better time to fix a mistake than now.

While we accept that this will cause some amount of "code churn" for
developers when they adopt Swift 5, the required change is a simple rename
that should be painless to automatically migrate. Of course, sample code
on the internet will become obsolete, but fix-its will easily update that
code if pasted into a project, and the samples themselves (once corrected)
should become clearer and easier to teach after this change, as is
generally true when overloading is removed.

Accordingly, SE-0187 is *accepted*, at least as far as not calling the
operation "flatMap". We are re-opening the review until next Monday,
November 20th, 2017, in order to have a focused discussion about the new
name. Names that seemed to gain some traction in the first review include:

  - filterMap, which has precedent in existing functional languages, as
well as some popular Swift libraries, but which some people view as
confusing

  - compactMap, which builds off the precedent of "compact" in Ruby

But please feel free to suggest a name other than these.

*Reviews*

Reviews are an important part of the Swift evolution process. All reviews
should be sent to the swift-evolution mailing list at

https://lists.swift.org/mailman/listinfo/swift-evolution

or, if you would like to keep your feedback private, directly to me as the
review manager. When replying, please try to keep the proposal link at the
top of the message:

Proposal link:

https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.md

Reply text

Other replies

*What goes into a review?*

The goal of the review process is to improve the proposal under review
through constructive criticism and, eventually, determine the direction of
Swift.

When writing your review, here are some questions you might want to answer
in your review:

• What is your evaluation of the proposal?
• Is the problem being addressed significant enough to warrant a change to
Swift?
• Does this proposal fit well with the feel and direction of Swift?
• If you have used other languages or libraries with a similar feature,
how do you feel that this proposal compares to those?
• How much effort did you put into your review? A glance, a quick reading,
or an in-depth study?

More information about the Swift evolution process is available at:

https://github.com/apple/swift-evolution/blob/master/process.md

As always, thank you for contributing to the evolution of Swift.

John McCall
Review Manager

_______________________________________________
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

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

filterMap is indeed an awkward name for this use case, just like flatMap is. In my experience, about half of my use cases use the identity closure, and half actually make use of the closure in a meaningful way. I would support a proposal to add something like Sequence.dropNils (actual name to be determined), and then we could let this proposal target the non-identity-closure use case.

-BJ

···

On Nov 20, 2017, at 10:09 AM, Drew Crawford via swift-evolution <swift-evolution@swift.org> wrote:

The typical case for this function in my code is the identity closure, that is

    let a: [Int?] = ...
    print(a.filterMap {$0})

filterMap is quite poor for this situation because *each* component in the term is inaccurate:

If the identity closure (i.e. "please remove the nils from this sequence") is a common use case, then I absolutely agree that we should consider adding a specific operation for that, and that name might illuminate the right name for the mapping version.

John.

···

On Nov 20, 2017, at 12:22 PM, BJ Homer <bjhomer@gmail.com> wrote:

On Nov 20, 2017, at 10:09 AM, Drew Crawford via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

The typical case for this function in my code is the identity closure, that is

    let a: [Int?] = ...
    print(a.filterMap {$0})

filterMap is quite poor for this situation because *each* component in the term is inaccurate:

filterMap is indeed an awkward name for this use case, just like flatMap is. In my experience, about half of my use cases use the identity closure, and half actually make use of the closure in a meaningful way. I would support a proposal to add something like Sequence.dropNils (actual name to be determined), and then we could let this proposal target the non-identity-closure use case.

I agree that filterMap is just as confusing and awkward as flatMap, if not more. Filter works on Bools, not nils. It is just asking for trouble/confusion, and I would hate to rename this again next year. If the word ‘filter’ must be used, then I recommend using ‘filteringMap()’ to lessen confusion with the filter method.

I like the idea of introducing compacted() and compactedMap(), though it only works if we introduce compacted() at the same time (which I am ok with). I keep expecting it to be a compact map in the topological sense, but I doubt that is a problem most will have.

The only real way to get forward transfer here (besides leaving it alone) is to do one of the following:

  • Use a name used by another language (that doesn’t conflict with Swift)

  • Introduce a concept of removing nils in Swift and call it the same thing (e.g. compacted)

  • Have an awkward, long, and overly specific name like mapAndRemoveNils

I think it might make sense to just drop the quest for forward transfer, and instead look for a short, readable, and memorable name that makes sense in hindsight once you have seen it (e.g. dropMap?). That, or introduce a word that means to remove nils.

Thanks,
Jon

···

On Nov 20, 2017, at 9:22 AM, BJ Homer via swift-evolution <swift-evolution@swift.org> wrote:

On Nov 20, 2017, at 10:09 AM, Drew Crawford via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

The typical case for this function in my code is the identity closure, that is

    let a: [Int?] = ...
    print(a.filterMap {$0})

filterMap is quite poor for this situation because *each* component in the term is inaccurate:

filterMap is indeed an awkward name for this use case, just like flatMap is. In my experience, about half of my use cases use the identity closure, and half actually make use of the closure in a meaningful way. I would support a proposal to add something like Sequence.dropNils (actual name to be determined), and then we could let this proposal target the non-identity-closure use case.

-BJ

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

The concern about filter changing types is only relevant if you think of the filter applying to the result of the map, instead of being a part of the filterMap operation itself (an operation that is distinct from map).

Let’s imagine that we had this instead:

enum SelectiveMapResult<T> {
    case use(T)
    case ignore
}

extension Sequence {
    func selectiveMap<T>(_ selectiveTransform: (Element)->SelectiveMapResult<T>) -> [T]
}

let actualNumbers =
    ["1", "2", "apple", "banana", "5"].selectiveMap({ (x)->SelectiveMapResult<Int> in
        if let value = Int(x) { return .use(value) }
        else { return .ignore }
    })

actualNumbers == [1, 2, 5]

The “selective” part of this operation doesn’t feel like it’s changing the type of the result, because SelectiveMapResult is easily understood to not be part of the mapping transformation; it just exists to tell us whether we should use the result of that particular transformation. Likewise, I don’t feel like the optional in filterMap is part of the mapping operation; it’s just serving the same role as SelectiveMapResult. (It should be obvious that SelectiveMapResult is just Optional with another name here.)

The name filterMap focuses on removing the ignored values, as does compactMap. The name selectiveMap focuses on retaining the non-ignored values. I’m not sure whether focusing on the positive or negative aspects is clearer here. I don’t particularly like the name compactMap, simply because I don’t have a lot of experience with languages that use “compact” to mean “drop the nil values”, and without that experience it doesn’t seem intuitive. I think filterMap is better. But if we introduced Sequence.compact() alongside .compactMap(), I’d probably get used to it.

-BJ

···

On Nov 15, 2017, at 3:05 PM, Tino Heth via swift-evolution <swift-evolution@swift.org> wrote:

Odd… exactly that is the reason why I think filterMap is the worst choice:

Both are established terms of art, but one has a meaning that doesn’t fit to the operation.
Applying filter can remove elements, but it can never change types (I feel kind of silly to repeat this over and over, but so far, nobody took the time to falsify this).

Odd… exactly that is the reason why I think filterMap is the worst choice:

Both are established terms of art, but one has a meaning that doesn’t fit to the operation.
Applying filter can remove elements, but it can never change types (I feel kind of silly to repeat this over and over, but so far, nobody took the time to falsify this).

The concern about filter changing types is only relevant if you think of the filter applying to the result of the map, instead of being a part of the filterMap operation itself (an operation that is distinct from map).

Let’s imagine that we had this instead:

enum SelectiveMapResult<T> {
    case use(T)
    case ignore
}

extension Sequence {
    func selectiveMap<T>(_ selectiveTransform: (Element)->SelectiveMapResult<T>) -> [T]
}

let actualNumbers =
    ["1", "2", "apple", "banana", "5"].selectiveMap({ (x)->SelectiveMapResult<Int> in
        if let value = Int(x) { return .use(value) }
        else { return .ignore }
    })

actualNumbers == [1, 2, 5]

The “selective” part of this operation doesn’t feel like it’s changing the type of the result, because SelectiveMapResult is easily understood to not be part of the mapping transformation; it just exists to tell us whether we should use the result of that particular transformation. Likewise, I don’t feel like the optional in filterMap is part of the mapping operation; it’s just serving the same role as SelectiveMapResult. (It should be obvious that SelectiveMapResult is just Optional with another name here.)

"selectiveMap" feels better in part due to grammar. "map" is obviously the verb and "selective" is obviously a modification of "map". "selectiveMap" is therefore performing some sort of special map operation.

"filterMap" feels bad for the same reason that "selectMap" would feel worse than "selectiveMap". "filter" and "map" are both verbs in this context. Grammatically the analogue to "selectiveMap" would be "filteredMap" or "filteringMap".

But even then "filteredMap" or "filteringMap" is insufficient to describe the operation. You additionally need to know that the "filter" here is not ordinary "filter", but instead the special case "filter { $0 != nil }".

The name filterMap focuses on removing the ignored values, as does compactMap. The name selectiveMap focuses on retaining the non-ignored values. I’m not sure whether focusing on the positive or negative aspects is clearer here. I don’t particularly like the name compactMap, simply because I don’t have a lot of experience with languages that use “compact” to mean “drop the nil values”, and without that experience it doesn’t seem intuitive. I think filterMap is better. But if we introduced Sequence.compact() alongside .compactMap(), I’d probably get used to it.

Swift doesn't use "filter" to mean "drop the nil values" either.

"compactMap" is okay if "compact" is added. Is "compact" a common enough operation in practice to pull its own weight?

"mapSome" is great if you know about Optional.Some but terrible if you don't. ("Okay, it maps some elements, but which ones?")

"mapNonNil" is obvious and ugly and perhaps its obviousness makes it a winner.

···

On Nov 15, 2017, at 2:31 PM, BJ Homer via swift-evolution <swift-evolution@swift.org> wrote:

On Nov 15, 2017, at 3:05 PM, Tino Heth via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

--
Greg Parker gparker@apple.com <mailto:gparker@apple.com> Runtime Wrangler

I thought it did map the non-nil values in the source sequence. Did I misunderstand what the proposed filterMap does? It occurs to me that the proposal does not have a standalone description of the filterMap operation.

···

On Nov 15, 2017, at 5:53 PM, John McCall <rjmccall@apple.com> wrote:

On Nov 15, 2017, at 7:36 PM, Greg Parker via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Nov 15, 2017, at 2:31 PM, BJ Homer via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Nov 15, 2017, at 3:05 PM, Tino Heth via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Odd… exactly that is the reason why I think filterMap is the worst choice:

Both are established terms of art, but one has a meaning that doesn’t fit to the operation.
Applying filter can remove elements, but it can never change types (I feel kind of silly to repeat this over and over, but so far, nobody took the time to falsify this).

The concern about filter changing types is only relevant if you think of the filter applying to the result of the map, instead of being a part of the filterMap operation itself (an operation that is distinct from map).

Let’s imagine that we had this instead:

enum SelectiveMapResult<T> {
    case use(T)
    case ignore
}

extension Sequence {
    func selectiveMap<T>(_ selectiveTransform: (Element)->SelectiveMapResult<T>) -> [T]
}

let actualNumbers =
    ["1", "2", "apple", "banana", "5"].selectiveMap({ (x)->SelectiveMapResult<Int> in
        if let value = Int(x) { return .use(value) }
        else { return .ignore }
    })

actualNumbers == [1, 2, 5]

The “selective” part of this operation doesn’t feel like it’s changing the type of the result, because SelectiveMapResult is easily understood to not be part of the mapping transformation; it just exists to tell us whether we should use the result of that particular transformation. Likewise, I don’t feel like the optional in filterMap is part of the mapping operation; it’s just serving the same role as SelectiveMapResult. (It should be obvious that SelectiveMapResult is just Optional with another name here.)

"selectiveMap" feels better in part due to grammar. "map" is obviously the verb and "selective" is obviously a modification of "map". "selectiveMap" is therefore performing some sort of special map operation.

"filterMap" feels bad for the same reason that "selectMap" would feel worse than "selectiveMap". "filter" and "map" are both verbs in this context. Grammatically the analogue to "selectiveMap" would be "filteredMap" or "filteringMap".

But even then "filteredMap" or "filteringMap" is insufficient to describe the operation. You additionally need to know that the "filter" here is not ordinary "filter", but instead the special case "filter { $0 != nil }".

The name filterMap focuses on removing the ignored values, as does compactMap. The name selectiveMap focuses on retaining the non-ignored values. I’m not sure whether focusing on the positive or negative aspects is clearer here. I don’t particularly like the name compactMap, simply because I don’t have a lot of experience with languages that use “compact” to mean “drop the nil values”, and without that experience it doesn’t seem intuitive. I think filterMap is better. But if we introduced Sequence.compact() alongside .compactMap(), I’d probably get used to it.

Swift doesn't use "filter" to mean "drop the nil values" either.

"compactMap" is okay if "compact" is added. Is "compact" a common enough operation in practice to pull its own weight?

"mapSome" is great if you know about Optional.Some but terrible if you don't. ("Okay, it maps some elements, but which ones?")

"mapNonNil" is obvious and ugly and perhaps its obviousness makes it a winner.

mapSome and especially mapNonNil both sound to me like they only map the non-nil values in the source sequence.

--
Greg Parker gparker@apple.com <mailto:gparker@apple.com> Runtime Wrangler

Having watched this discussion without much opinion before, I’ve found the argument about the meaning of map in a functional context to be somewhat convincing. While Swift isn’t a pure functional language, I think having the concept of a `map` generally mean a 1:1 mapping between input and output to be a good bit of consistency when thinking about it abstractly. Therefore I think a new verb is necessary, so compact is my choice, similar to flatten. While it could be considered a very specific version of filter, I think that it can stand on its own, as it also unwraps. So compact() would compact any array of optionals and compactMap() would map and then compact. While that sort of map isn’t 1:1, it’s in the line of normal flatMap, where the transform may change the number of elements in the result beyond a simple flattening of the array.
  As for popularity, personally I compact arrays of optionals far more than I flatten arrays of arrays. It’s especially useful in dealing with Objective-C types.
  Additionally, I think the logic I’ve just described justifies a flatten/flattened function to parallel flatMap. I know it would simplify my code, as I’m usually only flattening a single level of array without a transform.

Jon Shier

···

On Nov 15, 2017, at 7:36 PM, Greg Parker via swift-evolution <swift-evolution@swift.org> wrote:

On Nov 15, 2017, at 2:31 PM, BJ Homer via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Nov 15, 2017, at 3:05 PM, Tino Heth via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Odd… exactly that is the reason why I think filterMap is the worst choice:

Both are established terms of art, but one has a meaning that doesn’t fit to the operation.
Applying filter can remove elements, but it can never change types (I feel kind of silly to repeat this over and over, but so far, nobody took the time to falsify this).

The concern about filter changing types is only relevant if you think of the filter applying to the result of the map, instead of being a part of the filterMap operation itself (an operation that is distinct from map).

Let’s imagine that we had this instead:

enum SelectiveMapResult<T> {
    case use(T)
    case ignore
}

extension Sequence {
    func selectiveMap<T>(_ selectiveTransform: (Element)->SelectiveMapResult<T>) -> [T]
}

let actualNumbers =
    ["1", "2", "apple", "banana", "5"].selectiveMap({ (x)->SelectiveMapResult<Int> in
        if let value = Int(x) { return .use(value) }
        else { return .ignore }
    })

actualNumbers == [1, 2, 5]

The “selective” part of this operation doesn’t feel like it’s changing the type of the result, because SelectiveMapResult is easily understood to not be part of the mapping transformation; it just exists to tell us whether we should use the result of that particular transformation. Likewise, I don’t feel like the optional in filterMap is part of the mapping operation; it’s just serving the same role as SelectiveMapResult. (It should be obvious that SelectiveMapResult is just Optional with another name here.)

"selectiveMap" feels better in part due to grammar. "map" is obviously the verb and "selective" is obviously a modification of "map". "selectiveMap" is therefore performing some sort of special map operation.

"filterMap" feels bad for the same reason that "selectMap" would feel worse than "selectiveMap". "filter" and "map" are both verbs in this context. Grammatically the analogue to "selectiveMap" would be "filteredMap" or "filteringMap".

But even then "filteredMap" or "filteringMap" is insufficient to describe the operation. You additionally need to know that the "filter" here is not ordinary "filter", but instead the special case "filter { $0 != nil }".

The name filterMap focuses on removing the ignored values, as does compactMap. The name selectiveMap focuses on retaining the non-ignored values. I’m not sure whether focusing on the positive or negative aspects is clearer here. I don’t particularly like the name compactMap, simply because I don’t have a lot of experience with languages that use “compact” to mean “drop the nil values”, and without that experience it doesn’t seem intuitive. I think filterMap is better. But if we introduced Sequence.compact() alongside .compactMap(), I’d probably get used to it.

Swift doesn't use "filter" to mean "drop the nil values" either.

"compactMap" is okay if "compact" is added. Is "compact" a common enough operation in practice to pull its own weight?

"mapSome" is great if you know about Optional.Some but terrible if you don't. ("Okay, it maps some elements, but which ones?")

"mapNonNil" is obvious and ugly and perhaps its obviousness makes it a winner.

--
Greg Parker gparker@apple.com <mailto:gparker@apple.com> Runtime Wrangler

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