Well, in Swift as in other languages, to filter means to keep the stuff that matches the predicate. So it's not "filter nil" but "filter some." But actually, it's not a filter; it's a flat map operation, since the optional is being unwrapped.
Also, based on the precedent of "flat map," I think it really should be "filter map" and not "map filter," which would suggest incorrectly that the predicate would be for filtering. On Mon, Oct 23, 2017 at 22:38 Howard Lovatt via swift-evolution < swift-evolution@swift.org> wrote: > +1 good idea. > > Re. the naming I would suggest `mapFilterNil` since it says what it does > and filter, nil, and map are all understood already in Swift. (I have > sympathy for people wanting `mapFilteringNil`, but Swift chose `filter`.) > > The problems I see with `filterMap` are that: > > 1. It sounds like it is a merged `filter` and `map` and therefore you > would expect it to have two arguments, one to filter and one to map, i.e. > `filterMap<R>(filter: (T) -> Bool, map: (T) -> R) -> [R]`. > 2. It sounds like it will filter the incoming values (for `nil`, but see > 1 above) and then map, i.e. `filterMap<R>(map: (T?) -> R) -> [R]`, note > `T?` *not* `R?`. > > -- Howard. > > On 24 October 2017 at 11:56, BJ Homer via swift-evolution < > swift-evolution@swift.org> wrote: > >> I agree with Xiaodi; I like ‘filterMap’ more than ‘filteredMap’. But both >> are superior to ‘flatMap’ in this context. >> >> -BJ >> >> On Oct 23, 2017, at 5:22 PM, Max Moiseev <mois...@apple.com> wrote: >> >> It occurred to me that filteringMap(_:) should be even more descriptive, >> still conform to the guidelines, although similarly unprecedented and >> un-googlable. >> >> Max >> >> On Oct 23, 2017, at 3:52 PM, Xiaodi Wu <xiaodi...@gmail.com> wrote: >> >> +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@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@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@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 >> >> > _______________________________________________ > 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