[swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

Xiaodi Wu xiaodi.wu at gmail.com
Mon Oct 23 17:52:08 CDT 2017


+1 in general. As to the name: since 'map' is used as a term of art,
'filterMap' seems superior to 'filteredMap', which half follows naming
guidelines and half is a term of art; neither is immediately comprehensible
but 'filterMap' can be googled and has precedents in other languages.
On Mon, Oct 23, 2017 at 17:24 BJ Homer via swift-evolution <
swift-evolution at swift.org> wrote:

> I strongly agree! In fact, I just started writing up a similar proposal
> the other day, but hadn’t had time to finish it yet.
>
> The current name for this particular filtering variant is not particularly
> descriptive. It’s certainly not obvious to newcomers that ‘flatMap’ will
> filter out results. And it’s not true to the existing usage of ‘flatMap'
> from other languages; you have to really squint at it to see how any
> “flattening” is happening at all.
>
> So yes, a big +1 from me. Thanks!
>
> -BJ Homer
>
> On Oct 23, 2017, at 4:15 PM, Max Moiseev via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> Hi swift-evolution!
>
> I would like to propose the following change to the standard library:
>
> deprecate `Sequence.flatMap<U>(_: (Element) -> U?) -> [U]` and make this
> functionality available under a new name `Sequence.filteredMap(_:)`.
>
> The draft is available at
> https://gist.github.com/moiseev/2f36376c8ef4c2b1273cff0bfd9c3b95 and is
> included below for your convenience.
>
> Max
>
> Introduce Sequence.filteredMap(_:)
>
>    - Proposal: SE-NNNN <https://gist.github.com/moiseev/NNNN-filename.md>
>    - Authors: Max Moiseev <https://github.com/moiseev>
>    - Review Manager: TBD
>    - Status: Awaiting implementation
>
>
> <https://gist.github.com/moiseev/2f36376c8ef4c2b1273cff0bfd9c3b95#introduction>
> Introduction
>
> We propose to deprecate the controversial version of a Sequence.flatMap method
> and provide the same functionality under a different, and potentially more
> descriptive, name.
>
> <https://gist.github.com/moiseev/2f36376c8ef4c2b1273cff0bfd9c3b95#motivation>
> Motivation
>
> The Swift standard library currently defines 3 distinct overloads for
> flatMap:
>
> Sequence.flatMap<S>(_: (Element) -> S) -> [S.Element]
>     where S : SequenceOptional.flatMap<U>(_: (Wrapped) -> U?) -> U?Sequence.flatMap<U>(_: (Element) -> U?) -> [U]
>
> The last one, despite being useful in certain situations, can be (and
> often is) misused. Consider the following snippet:
>
> struct Person {
>   var age: Int
>   var name: String
> }
> func getAges(people: [Person]) -> [Int] {
>   return people.flatMap { $0.age }
> }
>
> What happens inside getNames is: thanks to the implicit promotion to
> Optional, the result of the closure gets wrapped into a .some, then
> immediately unwrapped by the implementation of flatMap, and appended to
> the result array. All this unnecessary wrapping and unwrapping can be
> easily avoided by just using map instead.
>
> func getAges(people: [Person]) -> [Int] {
>   return people.map { $0.age }
> }
>
> It gets even worse when we consider future code modifications, like the
> one where Swift 4 introduced a Stringconformance to the Collection protocol.
> The following code used to compile (due to the flatMap overload in
> question).
>
> func getNames(people: [Person]) -> [String] {
>   return people.flatMap { $0.name }
> }
>
> But it no longer does, because now there is a better overload that does
> not involve implicit promotion. In this particular case, the compiler error
> would be obvious, as it would point at the same line where flatMap is
> used. Imagine however if it was just a let names = people.flatMap { $
> 0.name } statement, and the names variable were used elsewhere. The
> compiler error would be misleading.
>
> <https://gist.github.com/moiseev/2f36376c8ef4c2b1273cff0bfd9c3b95#proposed-solution>Proposed
> solution
>
> We propose to deprecate the controversial overload of flatMap and
> re-introduce the same functionality under a new name. The name being
> filteredMap(_:) as we believe it best describes the intent of this
> function.
>
> For reference, here are the alternative names from other languages:
>
>    - Haskell, Idris  mapMaybe :: (a -> Maybe b) -> [a] -> [b]
>    - Ocaml (Core and Batteries)  filter_map : 'a t -> f:('a -> 'b option)
>    -> 'b t
>    - F#  List.choose : ('T -> 'U option) -> 'T list -> 'U list
>    - Rust  fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> where F:
>    FnMut(Self::Item) -> Option<B>
>    - Scala  def collect[B](pf: PartialFunction[A, B]): List[B]
>
>
> <https://gist.github.com/moiseev/2f36376c8ef4c2b1273cff0bfd9c3b95#source-compatibility>Source
> compatibility
>
> Since the old function will still be available (although deprecated) all
> the existing code will compile, producing a deprecation warning and a
> fix-it.
>
> <https://gist.github.com/moiseev/2f36376c8ef4c2b1273cff0bfd9c3b95#effect-on-abi-stability>Effect
> on ABI stability
>
> This is an additive API change, and does not affect ABI stability.
>
> <https://gist.github.com/moiseev/2f36376c8ef4c2b1273cff0bfd9c3b95#effect-on-api-resilience>Effect
> on API resilience
>
> Ideally, the deprecated flatMap overload would not exist at the time when
> ABI stability is declared, but in the worst case, it will be available in a
> deprecated form from a library post-ABI stability.
>
> <https://gist.github.com/moiseev/2f36376c8ef4c2b1273cff0bfd9c3b95#alternatives-considered>Alternatives
> considered
>
> It was attempted in the past to warn about this kind of misuse and do the
> right thing instead by means of a deprecated overload with a
> non-optional-returning closure. The attempt failed due to another implicit
> promotion (this time to Any).
>
> The following alternative names for this function were considered:
>
>    - mapNonNil(_:)  Does not communicate what happens to nil’s
>    - mapSome(_:)  Reads more like «map some elements of the sequence, but
>    not the others» rather than «process only the ones that produce an
>    Optional.some»
>    - filterMap(_:)  Does not really follow the naming guidelines and
>    doesn’t seem to be common enough to be considered a term of art.
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20171023/0dc43d51/attachment.html>


More information about the swift-evolution mailing list