+1 from me as well. —— Adrian Kashivskyy
On 24 Oct 2017, 00:24 +0200, BJ Homer via swift-evolution <[email protected]>, 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 > > <[email protected]> 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 > > • Authors: Max Moiseev > > • Review Manager: TBD > > • Status: Awaiting implementation > > > > 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. > > 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. > > 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] > > > > 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. > > Effect on ABI stability > > This is an additive API change, and does not affect ABI stability. > > 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. > > 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 > > [email protected] > > https://lists.swift.org/mailman/listinfo/swift-evolution >
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
