Huge +1 Calling "flatMap" a map + filtering out the nil values was a TERRIBLE idea.
Elviro > Il giorno 24 ott 2017, alle ore 00:15, Max Moiseev via swift-evolution > <swift-evolution@swift.org> ha scritto: > > 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 > <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 : Sequence > Optional.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@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