Having watched this discussion without much opinion before, I’ve found 
the argument about the meaning of map in a functional context to be somewhat 
convincing. While Swift isn’t a pure functional language, I think having the 
concept of a `map` generally mean a 1:1 mapping between input and output to be 
a good bit of consistency when thinking about it abstractly. Therefore I think 
a new verb is necessary, so compact is my choice, similar to flatten. While it 
could be considered a very specific version of filter, I think that it can 
stand on its own, as it also unwraps. So compact() would compact any array of 
optionals and compactMap() would map and then compact. While that sort of map 
isn’t 1:1, it’s in the line of normal flatMap, where the transform may change 
the number of elements in the result beyond a simple flattening of the array.
        As for popularity, personally I compact arrays of optionals far more 
than I flatten arrays of arrays. It’s especially useful in dealing with 
Objective-C types. 
        Additionally, I think the logic I’ve just described justifies a 
flatten/flattened function to parallel flatMap. I know it would simplify my 
code, as I’m usually only flattening a single level of array without a 
transform.


Jon Shier

> On Nov 15, 2017, at 7:36 PM, Greg Parker via swift-evolution 
> <swift-evolution@swift.org> wrote:
> 
>> 
>> On Nov 15, 2017, at 2:31 PM, BJ Homer via swift-evolution 
>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>> 
>>> On Nov 15, 2017, at 3:05 PM, Tino Heth via swift-evolution 
>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>>> 
>>> Odd… exactly that is the reason why I think filterMap is the worst choice:
>>> 
>>> Both are established terms of art, but one has a meaning that doesn’t fit 
>>> to the operation.
>>> Applying filter can remove elements, but it can never change types (I feel 
>>> kind of silly to repeat this over and over, but so far, nobody took the 
>>> time to falsify this).
>> 
>> The concern about filter changing types is only relevant if you think of the 
>> filter applying to the result of the map, instead of being a part of the 
>> filterMap operation itself (an operation that is distinct from map).
>> 
>> Let’s imagine that we had this instead:
>> 
>> enum SelectiveMapResult<T> {
>>     case use(T)
>>     case ignore
>> }
>> 
>> extension Sequence {
>>     func selectiveMap<T>(_ selectiveTransform: 
>> (Element)->SelectiveMapResult<T>) -> [T]
>> }
>> 
>> let actualNumbers =
>>     ["1", "2", "apple", "banana", "5"].selectiveMap({ 
>> (x)->SelectiveMapResult<Int> in
>>         if let value = Int(x) { return .use(value) }
>>         else { return .ignore }
>>     })
>> 
>> actualNumbers == [1, 2, 5]
>> 
>> The “selective” part of this operation doesn’t feel like it’s changing the 
>> type of the result, because SelectiveMapResult is easily understood to not 
>> be part of the mapping transformation; it just exists to tell us whether we 
>> should use the result of that particular transformation. Likewise, I don’t 
>> feel like the optional in filterMap is part of the mapping operation; it’s 
>> just serving the same role as SelectiveMapResult. (It should be obvious that 
>> SelectiveMapResult is just Optional with another name here.)
> 
> "selectiveMap" feels better in part due to grammar. "map" is obviously the 
> verb and "selective" is obviously a modification of "map". "selectiveMap" is 
> therefore performing some sort of special map operation. 
> 
> "filterMap" feels bad for the same reason that "selectMap" would feel worse 
> than "selectiveMap". "filter" and "map" are both verbs in this context. 
> Grammatically the analogue to "selectiveMap" would be "filteredMap" or 
> "filteringMap". 
> 
> But even then "filteredMap" or "filteringMap" is insufficient to describe the 
> operation. You additionally need to know that the "filter" here is not 
> ordinary "filter", but instead the special case "filter { $0 != nil }".
> 
> 
>> The name filterMap focuses on removing the ignored values, as does 
>> compactMap. The name selectiveMap focuses on retaining the non-ignored 
>> values. I’m not sure whether focusing on the positive or negative aspects is 
>> clearer here. I don’t particularly like the name compactMap, simply because 
>> I don’t have a lot of experience with languages that use “compact” to mean 
>> “drop the nil values”, and without that experience it doesn’t seem 
>> intuitive. I think filterMap is better. But if we introduced 
>> Sequence.compact() alongside .compactMap(), I’d probably get used to it.
> 
> Swift doesn't use "filter" to mean "drop the nil values" either. 
> 
> 
> "compactMap" is okay if "compact" is added. Is "compact" a common enough 
> operation in practice to pull its own weight?
> 
> "mapSome" is great if you know about Optional.Some but terrible if you don't. 
> ("Okay, it maps some elements, but which ones?") 
> 
> "mapNonNil" is obvious and ugly and perhaps its obviousness makes it a winner.
> 
> 
> -- 
> Greg Parker     gpar...@apple.com <mailto:gpar...@apple.com>     Runtime 
> Wrangler
> 
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> <https://lists.swift.org/mailman/listinfo/swift-evolution>
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to