Re: [swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-27 Thread Tino Heth via swift-evolution

> I wrote about this in 2015
> http://alejandromp.com/blog/2015/6/24/swift-flatmap/ 
>  and forgot about
> it.
That text has a line which illustrates the source of dissent:

> It’s kind of combining map (to apply the function), flatten (to unwrap the 
> optionals) and filter (to remove the nils)


I’m saying this isn’t true, because after the flatten step, there are no 
Optionals left, and thus, there can be no nils at all (unless we startet with 
Optional…)

(hope this doesn’t arrive twice — imho Mail.app really should be retired for 
this kind of discussion ;-)___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-27 Thread Tino via swift-evolution

> I wrote about this in 2015
> http://alejandromp.com/blog/2015/6/24/swift-flatmap/ 
>  and forgot about
> it.
That text has a line which illustrates the source of dissent:

> It’s kind of combining map (to apply the function), flatten (to unwrap the 
> optionals) and filter (to remove the nils)


I’m saying this isn’t true, because after the flatten step, there are no 
Optionals left, and thus, there can be no nils at all (unless we startet with 
Optional…)___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-27 Thread David Waite via swift-evolution
I'm not attached to the name filteredMap, but having a specific signature for 
the optional version makes sense. 

I think the problem is that while Optional can be contemplated as a sequence of 
zero or one items, implicit conversion to Optional means anything can then be 
interpreted as a collection of one item.

Likewise, if the syntax for passing in closures required any argument label to 
be specified, it might be clearer for optional vs sequence, but they are not 
required.

-DW

> On Oct 23, 2017, at 4:15 PM, Max Moiseev via swift-evolution 
>  wrote:
> 
> Hi swift-evolution!
> 
> I would like to propose the following change to the standard library:
> 
> deprecate `Sequence.flatMap(_: (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- 
> 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(_: (Element) -> S) -> [S.Element]
> where S : Sequence
> Optional.flatMap(_: (Wrapped) -> U?) -> U?
> Sequence.flatMap(_: (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(self, f: F) -> FilterMap
>  where F: 
> FnMut(Self::Item) -> Option
> 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.
> 
>  
> 

Re: [swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-26 Thread Alejandro Martinez via swift-evolution
I wrote about this in 2015
http://alejandromp.com/blog/2015/6/24/swift-flatmap/ and forgot about
it.
I just get used to it now but it's still hard to explain to newcomers
why flatMap has this "special" behaviour on Swift.
I'm not an expert on functional programming but if this doesn't make
sense in the theory and it's just for convenience I agree we could
rename it. Still, if it has some reason to work like this (higher
kinded types?) and we expect to have them in an infinite time scale...
maybe we should hold on.

On Wed, Oct 25, 2017 at 7:06 PM, Max Moiseev via swift-evolution
 wrote:
>
>
> On Oct 25, 2017, at 2:15 AM, Tino <2...@gmx.de> wrote:
>
>
> It’s unfortunate when a piece of code gets a different meaning — but as you
> said:
> It’s a misuse, and when you write code that is wrong, the results might be
> wrong as well.
>
> And this is exactly that we’re trying to address. Not the impurity of the
> function, not the performance, but the potential to misuse.
>
> But do you think filterMap can’t be misused? I don’t know why people choose
> flatMap instead of map, but they might as well just switch to filterMap.
>
> Oh I’m sure they will. But I hope it will be harder, because we will have a
> deprecated overload of a flatMap that will provide a helpful message and
> guide people to use map instead.
>
>
> Maybe Scala chose better name for the concept, but the Swift definition is
> consistent as it is now.
>
> collect does not say anything about the transformation (A => B) that happens
> along the way…
>
> „collectResults“ is probably clearer… but I guess Scala-folks choose to
> prefer a single word.
>
> Let’s not forget about the types. Function type is an essential piece of
> information that should accompany it’s name. With a function type being
> (LIst[A], PartialFunction[A, B]) => List[B] the name is almost not needed,
> there is pretty much one way of implementing this function (if we forget
> about trivial and wrong implementations that, for example, return an empty
> list all the time, of perform arbitrary side-effects).
>
> But when it’s about clear naming, we probably should talk about
> „applyFunctionAndCollectUnwrappedResults“, because filtering has no obvious
> connection to nil-values.
> Even worse, I think filter is the wrong word in this context, because that’s
> what I’d expect from such a function:
>
> Sequence.filterMap(_: (Element) -> U?) -> [U?]
>
>
> In this case, the result would only contain those Optionals that contain a
> value — or there could be a parameter for the filter, defaulted to a check
> for nil.
>
> So, if you remove the third overload, the second one imho should be renamed,
> too.
>
> Honestly, I don’t see why. Can you elaborate? The second one is perfectly
> consistent, it does not mix two different functor instances in the same
> function.
>
> As it is now, both Sequence and Optional are very similar — they are
> container types that may be empty.
> When you say that one incarnation of flatMap that deals with Optionals is
> wrong, imho it’s cleaner to break that connection completely, and make it a
> Collection-only thing.
> Overload 2 is kind of a special case of the third one.
>
> I was actually thinking in the opposite direction ;-) As in, adding more
> functions from Collection to Optional. filter can be useful, count, isEmpty,
> forEach… I’m not saying that it will conform to the Collection protocol, but
> I can see how sometimes `opt.filter { $0 > 0 }` is a better option than `if
> let v = opt, x > 0 { … } else { … }
>
>
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>



-- 
Alejandro Martinez
http://alejandromp.com
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-25 Thread Max Moiseev via swift-evolution


> On Oct 25, 2017, at 2:15 AM, Tino <2...@gmx.de> wrote:
> 
> 
>>> It’s unfortunate when a piece of code gets a different meaning — but as you 
>>> said:
>>> It’s a misuse, and when you write code that is wrong, the results might be 
>>> wrong as well.
>> And this is exactly that we’re trying to address. Not the impurity of the 
>> function, not the performance, but the potential to misuse.
> But do you think filterMap can’t be misused? I don’t know why people choose 
> flatMap instead of map, but they might as well just switch to filterMap.
Oh I’m sure they will. But I hope it will be harder, because we will have a 
deprecated overload of a flatMap that will provide a helpful message and guide 
people to use map instead.
> 
>>> Maybe Scala chose better name for the concept, but the Swift definition is 
>>> consistent as it is now.
>> collect does not say anything about the transformation (A => B) that happens 
>> along the way…
> „collectResults“ is probably clearer… but I guess Scala-folks choose to 
> prefer a single word.
Let’s not forget about the types. Function type is an essential piece of 
information that should accompany it’s name. With a function type being 
(LIst[A], PartialFunction[A, B]) => List[B] the name is almost not needed, 
there is pretty much one way of implementing this function (if we forget about 
trivial and wrong implementations that, for example, return an empty list all 
the time, of perform arbitrary side-effects).

> But when it’s about clear naming, we probably should talk about 
> „applyFunctionAndCollectUnwrappedResults“, because filtering has no obvious 
> connection to nil-values.
> Even worse, I think filter is the wrong word in this context, because that’s 
> what I’d expect from such a function:
> Sequence.filterMap(_: (Element) -> U?) -> [U?]
> 
> In this case, the result would only contain those Optionals that contain a 
> value — or there could be a parameter for the filter, defaulted to a check 
> for nil.
> 
>>> So, if you remove the third overload, the second one imho should be 
>>> renamed, too.
>> Honestly, I don’t see why. Can you elaborate? The second one is perfectly 
>> consistent, it does not mix two different functor instances in the same 
>> function.
> As it is now, both Sequence and Optional are very similar — they are 
> container types that may be empty.
> When you say that one incarnation of flatMap that deals with Optionals is 
> wrong, imho it’s cleaner to break that connection completely, and make it a 
> Collection-only thing.
> Overload 2 is kind of a special case of the third one.
I was actually thinking in the opposite direction ;-) As in, adding more 
functions from Collection to Optional. filter can be useful, count, isEmpty, 
forEach… I’m not saying that it will conform to the Collection protocol, but I 
can see how sometimes `opt.filter { $0 > 0 }` is a better option than `if let v 
= opt, x > 0 { … } else { … }

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-25 Thread Tino via swift-evolution

>> It’s unfortunate when a piece of code gets a different meaning — but as you 
>> said:
>> It’s a misuse, and when you write code that is wrong, the results might be 
>> wrong as well.
> And this is exactly that we’re trying to address. Not the impurity of the 
> function, not the performance, but the potential to misuse.
But do you think filterMap can’t be misused? I don’t know why people choose 
flatMap instead of map, but they might as well just switch to filterMap.

>> Maybe Scala chose better name for the concept, but the Swift definition is 
>> consistent as it is now.
> collect does not say anything about the transformation (A => B) that happens 
> along the way…
„collectResults“ is probably clearer… but I guess Scala-folks choose to prefer 
a single word.
But when it’s about clear naming, we probably should talk about 
„applyFunctionAndCollectUnwrappedResults“, because filtering has no obvious 
connection to nil-values.
Even worse, I think filter is the wrong word in this context, because that’s 
what I’d expect from such a function:
Sequence.filterMap(_: (Element) -> U?) -> [U?]

In this case, the result would only contain those Optionals that contain a 
value — or there could be a parameter for the filter, defaulted to a check for 
nil.

>> So, if you remove the third overload, the second one imho should be renamed, 
>> too.
> Honestly, I don’t see why. Can you elaborate? The second one is perfectly 
> consistent, it does not mix two different functor instances in the same 
> function.
As it is now, both Sequence and Optional are very similar — they are container 
types that may be empty.
When you say that one incarnation of flatMap that deals with Optionals is 
wrong, imho it’s cleaner to break that connection completely, and make it a 
Collection-only thing.
Overload 2 is kind of a special case of the third one.___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-24 Thread Max Moiseev via swift-evolution


> On Oct 24, 2017, at 11:36 AM, Tino <2...@gmx.de> wrote:
> 
> 
>>> If the biggest problem of flatMap is that people who don’t understand it 
>>> write code that isn’t optimal (but still does the right thing!), I don’t 
>>> think there is any change needed. I’m not even sure that that 
>>> wrapping/unwrapping is actually done, because it should be discoverable by 
>>> the compiler.
>> It can be seen that the generated SIL is more complicated for a flatMap 
>> case, the microbenchmark also shows that it’s about 3x slower than the map. 
>> But even if that can be optimized away, don’t you find a String example from 
>> the proposal even a little convincing?
> It’s unfortunate when a piece of code gets a different meaning — but as you 
> said:
> It’s a misuse, and when you write code that is wrong, the results might be 
> wrong as well.
And this is exactly that we’re trying to address. Not the impurity of the 
function, not the performance, but the potential to misuse.
> 
> Maybe Scala chose better name for the concept, but the Swift definition is 
> consistent as it is now.
collect does not say anything about the transformation (A => B) that happens 
along the way…

> So, if you remove the third overload, the second one imho should be renamed, 
> too.
Honestly, I don’t see why. Can you elaborate? The second one is perfectly 
consistent, it does not mix two different functor instances in the same 
function.

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-24 Thread Tino via swift-evolution

>> If the biggest problem of flatMap is that people who don’t understand it 
>> write code that isn’t optimal (but still does the right thing!), I don’t 
>> think there is any change needed. I’m not even sure that that 
>> wrapping/unwrapping is actually done, because it should be discoverable by 
>> the compiler.
> It can be seen that the generated SIL is more complicated for a flatMap case, 
> the microbenchmark also shows that it’s about 3x slower than the map. But 
> even if that can be optimized away, don’t you find a String example from the 
> proposal even a little convincing?
It’s unfortunate when a piece of code gets a different meaning — but as you 
said:
It’s a misuse, and when you write code that is wrong, the results might be 
wrong as well.

Maybe Scala chose better name for the concept, but the Swift definition is 
consistent as it is now.
So, if you remove the third overload, the second one imho should be renamed, 
too.___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-24 Thread Max Moiseev via swift-evolution


> On Oct 23, 2017, at 8:38 PM, Howard Lovatt  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`.)
`nil` is an overloaded term, since there is ExpressibleByNilLiteral, and pretty 
much any type can conform to it.

> 
> 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(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(map: (T?) -> R) -> [R]`, note `T?` 
> *not* `R?`.
> 
>   -- Howard.
> 
> On 24 October 2017 at 11:56, BJ Homer via swift-evolution 
> > 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  > 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 >> > 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 
>>> > 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 
 > wrote:
 
 Hi swift-evolution!
 
 I would like to propose the following change to the standard library:
 
 deprecate `Sequence.flatMap(_: (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- 
 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(_: (Element) -> S) -> [S.Element]
 where S : Sequence
 Optional.flatMap(_: (Wrapped) -> U?) -> U?
 Sequence.flatMap(_: (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 

Re: [swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-24 Thread Max Moiseev via swift-evolution


> On Oct 24, 2017, at 5:10 AM, Tino <2...@gmx.de> wrote:
> 
> 
>> Calling "flatMap" a map + filtering out the nil values was a TERRIBLE idea.
> maybe I’m the one who’s getting this all wrong, but afaik the purpose of 
> flatMap isn’t filtering out nil at all, but just a combination of map & 
> flatten…
> Optional is like Array with a maximal capacity of one (so it can either 
> contain a single object, or it’s empty), and in this interpretation, there’s 
> nothing wrong with the behavior.

> 
> Instead, I think Nobuo Saito is right, and that a renaming to filteredMap is 
> only fighting symptoms, and not the cause (but I’m not that sure if there’s a 
> good way to tackle the cause).
> Besides that, all those alternative names also have potential for confusion:
> Imho it isn’t intuitive what is filtered out — and don’t forget that the 
> result of flatMap can contain nil elements…
> 
> If the biggest problem of flatMap is that people who don’t understand it 
> write code that isn’t optimal (but still does the right thing!), I don’t 
> think there is any change needed. I’m not even sure that that 
> wrapping/unwrapping is actually done, because it should be discoverable by 
> the compiler.
It can be seen that the generated SIL is more complicated for a flatMap case, 
the microbenchmark also shows that it’s about 3x slower than the map. But even 
if that can be optimized away, don’t you find a String example from the 
proposal even a little convincing?
> 
> It would be nice if there was an way to warn in places where flatMap could be 
> replaced with map, though (but imho this special warning shouldn’t be checked 
> by the compiler).
I tried to avoid renaming: https://github.com/apple/swift/pull/7823/ 
 but then 
https://github.com/apple/swift/pull/9390 
.
> 
> - Tino

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-24 Thread Matthew Johnson via swift-evolution

> On Oct 24, 2017, at 1:57 AM, David Hart via swift-evolution 
>  wrote:
> 
> I also cast my vote for filterMap. It’s concise, understandable and is kind 
> of a term of art also.

+1.  This seems like the best option to me.

> 
>> On 24 Oct 2017, at 02:56, BJ Homer via swift-evolution 
>> > 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 > > 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 > 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 
 > 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 
> > wrote:
> 
> Hi swift-evolution!
> 
> I would like to propose the following change to the standard library:
> 
> deprecate `Sequence.flatMap(_: (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- 
> 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(_: (Element) -> S) -> [S.Element]
> where S : Sequence
> Optional.flatMap(_: (Wrapped) -> U?) -> U?
> Sequence.flatMap(_: (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 

Re: [swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-24 Thread Elviro Rocca via swift-evolution
"Flattening" in the context of functional programming (and that's where map and 
flatMap come from) means something like this:

F -> F

So for example:

Array -> Array

or

Optional -> Optional

but NOT:

Array -> Array

It's simply the wrong word for the operation.

If "Map" is something like this:

(F + (T -> U)) -> F

then "FlatMap" means "map to the same functor, then flatten", thus:

(F + (A -> F)) -> F
then 
(F -> F)

In this case "U == F"

In fact, there's (rightfully) a FlatMap method on Optional in cases in which 
the mapping function produces another Optional (notice that the chained 
unwrapping with "?." is a FlatMap operation).

Calling FlatMap something that is not (in the literature and community at 
large) was not a good idea, in my opinion.

Elviro

> Il giorno 24 ott 2017, alle ore 14:10, Tino <2...@gmx.de> ha scritto:
> 
> 
>> Calling "flatMap" a map + filtering out the nil values was a TERRIBLE idea.
> maybe I’m the one who’s getting this all wrong, but afaik the purpose of 
> flatMap isn’t filtering out nil at all, but just a combination of map & 
> flatten…
> Optional is like Array with a maximal capacity of one (so it can either 
> contain a single object, or it’s empty), and in this interpretation, there’s 
> nothing wrong with the behavior.
> 
> Instead, I think Nobuo Saito is right, and that a renaming to filteredMap is 
> only fighting symptoms, and not the cause (but I’m not that sure if there’s a 
> good way to tackle the cause).
> Besides that, all those alternative names also have potential for confusion:
> Imho it isn’t intuitive what is filtered out — and don’t forget that the 
> result of flatMap can contain nil elements…
> 
> If the biggest problem of flatMap is that people who don’t understand it 
> write code that isn’t optimal (but still does the right thing!), I don’t 
> think there is any change needed. I’m not even sure that that 
> wrapping/unwrapping is actually done, because it should be discoverable by 
> the compiler.
> 
> It would be nice if there was an way to warn in places where flatMap could be 
> replaced with map, though (but imho this special warning shouldn’t be checked 
> by the compiler).
> 
> - Tino

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-24 Thread Tino via swift-evolution

> Calling "flatMap" a map + filtering out the nil values was a TERRIBLE idea.
maybe I’m the one who’s getting this all wrong, but afaik the purpose of 
flatMap isn’t filtering out nil at all, but just a combination of map & flatten…
Optional is like Array with a maximal capacity of one (so it can either 
contain a single object, or it’s empty), and in this interpretation, there’s 
nothing wrong with the behavior.

Instead, I think Nobuo Saito is right, and that a renaming to filteredMap is 
only fighting symptoms, and not the cause (but I’m not that sure if there’s a 
good way to tackle the cause).
Besides that, all those alternative names also have potential for confusion:
Imho it isn’t intuitive what is filtered out — and don’t forget that the result 
of flatMap can contain nil elements…

If the biggest problem of flatMap is that people who don’t understand it write 
code that isn’t optimal (but still does the right thing!), I don’t think there 
is any change needed. I’m not even sure that that wrapping/unwrapping is 
actually done, because it should be discoverable by the compiler.

It would be nice if there was an way to warn in places where flatMap could be 
replaced with map, though (but imho this special warning shouldn’t be checked 
by the compiler).

- Tino___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-24 Thread Adrian Kashivskyy via swift-evolution
+1 from me as well.

——
Adrian Kashivskyy

On 24 Oct 2017, 00:24 +0200, BJ Homer via swift-evolution 
, 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 
> >  wrote:
> >
> > Hi swift-evolution!
> >
> > I would like to propose the following change to the standard library:
> >
> > deprecate `Sequence.flatMap(_: (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-
> > • 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(_: (Element) -> S) -> [S.Element]
> >where S : Sequence
> > Optional.flatMap(_: (Wrapped) -> U?) -> U?
> > Sequence.flatMap(_: (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(self, f: F) -> FilterMap where F: 
> > FnMut(Self::Item) -> Option
> > • 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
> > • 

Re: [swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-24 Thread Elviro Rocca via swift-evolution
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 
>  ha scritto:
> 
> Hi swift-evolution!
> 
> I would like to propose the following change to the standard library:
> 
> deprecate `Sequence.flatMap(_: (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- 
> 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(_: (Element) -> S) -> [S.Element]
> where S : Sequence
> Optional.flatMap(_: (Wrapped) -> U?) -> U?
> Sequence.flatMap(_: (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(self, f: F) -> FilterMap
>  where F: 
> FnMut(Self::Item) -> Option
> 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 

Re: [swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-24 Thread David Hart via swift-evolution
I also cast my vote for filterMap. It’s concise, understandable and is kind of 
a term of art also.

> On 24 Oct 2017, at 02:56, BJ Homer via swift-evolution 
>  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  > 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 >> > 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 
>>> > 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 
 > wrote:
 
 Hi swift-evolution!
 
 I would like to propose the following change to the standard library:
 
 deprecate `Sequence.flatMap(_: (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- 
 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(_: (Element) -> S) -> [S.Element]
 where S : Sequence
 Optional.flatMap(_: (Wrapped) -> U?) -> U?
 Sequence.flatMap(_: (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

Re: [swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-24 Thread Nobuo Saito via swift-evolution
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 <
swift-evolution@swift.org>:

> Hi swift-evolution!
>
> I would like to propose the following change to the standard library:
>
> deprecate `Sequence.flatMap(_: (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- 
>- 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(_: (Element) -> S) -> [S.Element]
> where S : SequenceOptional.flatMap(_: (Wrapped) -> U?) -> 
> U?Sequence.flatMap(_: (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(self, f: F) -> FilterMap where F:
>FnMut(Self::Item) -> Option
>- 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 

Re: [swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-23 Thread Thorsten Seitz via swift-evolution
Well, I have no problems with `flatMap` but then I am used to Monads.
I would not rename that overload if there is any hope that we might get Monads 
sometime in the future but probably there is none (which is sad).

So I would suggest `mapDroppingNil` or maybe `mapRejectingNil`.

-Thorsten


> Am 24.10.2017 um 05:38 schrieb Howard Lovatt via swift-evolution 
> :
> 
> +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(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(map: (T?) -> R) -> [R]`, note `T?` 
> *not* `R?`.
> 
>   -- Howard.
> 
>> On 24 October 2017 at 11:56, BJ Homer via swift-evolution 
>>  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  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  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 
  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 
>>  wrote:
>> 
>> Hi swift-evolution!
>> 
>> I would like to propose the following change to the standard library:
>> 
>> deprecate `Sequence.flatMap(_: (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-
>> 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(_: (Element) -> S) -> [S.Element]
>> where S : Sequence
>> Optional.flatMap(_: (Wrapped) -> U?) -> U?
>> Sequence.flatMap(_: (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 

Re: [swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-23 Thread Xiaodi Wu via swift-evolution
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(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(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  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  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(_: (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-
>>>
>>>- 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(_: (Element) -> S) -> [S.Element]
>>> where S : SequenceOptional.flatMap(_: (Wrapped) -> U?) -> 
>>> U?Sequence.flatMap(_: (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
>>> 

Re: [swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-23 Thread Howard Lovatt via swift-evolution
+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(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(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  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  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(_: (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- 
>>- 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(_: (Element) -> S) -> [S.Element]
>> where S : SequenceOptional.flatMap(_: (Wrapped) -> U?) -> 
>> U?Sequence.flatMap(_: (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 

Re: [swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-23 Thread BJ Homer via swift-evolution
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  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  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 
>>  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 
  wrote:
 
 Hi swift-evolution!
 
 I would like to propose the following change to the standard library:
 
 deprecate `Sequence.flatMap(_: (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-
 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(_: (Element) -> S) -> [S.Element]
 where S : Sequence
 Optional.flatMap(_: (Wrapped) -> U?) -> U?
 Sequence.flatMap(_: (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(self, f: F) -> FilterMap
  
 where F: FnMut(Self::Item) -> Option
 Scala 
 def collect[B](pf: PartialFunction[A, B]): List[B]
 Source compatibility
 
 Since the old 

Re: [swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-23 Thread Max Moiseev via swift-evolution
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  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 
> > 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 
>> > wrote:
>> 
>> Hi swift-evolution!
>> 
>> I would like to propose the following change to the standard library:
>> 
>> deprecate `Sequence.flatMap(_: (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- 
>> 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(_: (Element) -> S) -> [S.Element]
>> where S : Sequence
>> Optional.flatMap(_: (Wrapped) -> U?) -> U?
>> Sequence.flatMap(_: (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(self, f: F) -> FilterMap
>>  where F: 
>> FnMut(Self::Item) -> Option
>> Scala 
>> def collect[B](pf: PartialFunction[A, B]): List[B]

Re: [swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-23 Thread Xiaodi Wu via swift-evolution
On Mon, Oct 23, 2017 at 6:11 PM, Braden Scothern 
wrote:

> The reason `flatMap(_:)` has its name is for code like this:
>
> ```
> let nestedArray = [[1, 2, 3], [4, 5, 6]]
> let flatArray = nestedArray.flatMap {
> $0
> }
>
> print(flatArray) // prints [1, 2, 3, 4, 5, 6]
>
> let anotherNestedArrays = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
> let anotherFlatArray = anotherNestedArray.flatMap {
> $0
> }
>
> print(anotherFlatArray) // prints [[1, 2], [3, 4], [5, 6], [7, 8]]
> ```
>
> Do your examples from other languages have this behavior of flattening
> nested sequences by 1 layer? Do you think it makes sense to have this
> effect as part of your proposed rename?
>
> I feel like the name `filteredMap(_:)` implies that the result should keep
> the same structure as the original Sequence type which doesn't allow for
> the flattening.
>
> If these 2 pieces of functionality weren't already a part of one function
> or if you proposal had a good solution to address this other part
> functionality, I would be accepting of a name change. I haven't ever been a
> fan of flatMap(_:) having 2 jobs, but it has been this way since Swift 1 or
> 2.
>

`flatMap` is not going away or being renamed. One particular overload is
being renamed so that the other overloads work as expected.


> Also, I don't think the name `filterMap` makes sense with Swift naming
> conventions. To me it implies that you are going to map in place vs the
> filtered makes it clear you are creating a new Array to return. I really
> like the sort() vs sorted() naming convention that is already the standard
> for Swift code and would rather any name changes stick to that.
>

`map`, `filter` and `flatMap` are settled exceptions to the Swift naming
conventions because they are terms of art, and that's not changing going
forward.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-23 Thread Braden Scothern via swift-evolution
The reason `flatMap(_:)` has its name is for code like this:

```
let nestedArray = [[1, 2, 3], [4, 5, 6]]
let flatArray = nestedArray.flatMap {
$0
}

print(flatArray) // prints [1, 2, 3, 4, 5, 6]

let anotherNestedArrays = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
let anotherFlatArray = anotherNestedArray.flatMap {
$0
}

print(anotherFlatArray) // prints [[1, 2], [3, 4], [5, 6], [7, 8]]
```

Do your examples from other languages have this behavior of flattening
nested sequences by 1 layer? Do you think it makes sense to have this
effect as part of your proposed rename?

I feel like the name `filteredMap(_:)` implies that the result should keep
the same structure as the original Sequence type which doesn't allow for
the flattening.

If these 2 pieces of functionality weren't already a part of one function
or if you proposal had a good solution to address this other part
functionality, I would be accepting of a name change. I haven't ever been a
fan of flatMap(_:) having 2 jobs, but it has been this way since Swift 1 or
2.


Also, I don't think the name `filterMap` makes sense with Swift naming
conventions. To me it implies that you are going to map in place vs the
filtered makes it clear you are creating a new Array to return. I really
like the sort() vs sorted() naming convention that is already the standard
for Swift code and would rather any name changes stick to that.

On Mon, Oct 23, 2017 at 4:52 PM, Xiaodi Wu via swift-evolution <
swift-evolution@swift.org> 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(_: (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- 
>>- 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(_: (Element) -> S) -> [S.Element]
>> where S : SequenceOptional.flatMap(_: (Wrapped) -> U?) -> 
>> U?Sequence.flatMap(_: (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 

Re: [swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-23 Thread Xiaodi Wu via swift-evolution
+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(_: (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- 
>- 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(_: (Element) -> S) -> [S.Element]
> where S : SequenceOptional.flatMap(_: (Wrapped) -> U?) -> 
> U?Sequence.flatMap(_: (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(self, f: F) -> FilterMap where F:
>FnMut(Self::Item) -> Option
>- 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.
>
> 

Re: [swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-23 Thread BJ Homer via swift-evolution
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 
>  wrote:
> 
> Hi swift-evolution!
> 
> I would like to propose the following change to the standard library:
> 
> deprecate `Sequence.flatMap(_: (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- 
> 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(_: (Element) -> S) -> [S.Element]
> where S : Sequence
> Optional.flatMap(_: (Wrapped) -> U?) -> U?
> Sequence.flatMap(_: (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(self, f: F) -> FilterMap
>  where F: 
> FnMut(Self::Item) -> Option
> 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.
> 
>  
> 

[swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-23 Thread Max Moiseev via swift-evolution
Hi swift-evolution!

I would like to propose the following change to the standard library:

deprecate `Sequence.flatMap(_: (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- 
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(_: (Element) -> S) -> [S.Element]
where S : Sequence
Optional.flatMap(_: (Wrapped) -> U?) -> U?
Sequence.flatMap(_: (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(self, f: F) -> FilterMap
 where F: 
FnMut(Self::Item) -> Option
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