Hi there, In my opinion, `map` vs `flatMap` confusing comes from implicitly casting `T` to `T?`. I believe it make many confusing and problems that compiler allow this implicitly casting. 1 way of solve this topic that show warning if use implicitly casting `T` to `T?`. Of course it should be explict casting can avoid this warning. Such as `x as Int?`, `Int?.some(x)`, `intClosure as (() -> Int?)`.
2017-10-24 7:15 GMT+09:00 Max Moiseev via swift-evolution < [email protected]>: > 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/moi > seev/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 > [email protected] > https://lists.swift.org/mailman/listinfo/swift-evolution > >
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
