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

Reply via email to