Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FlatMap gives warning with Int type array but not with String type array

Tags:

ios

swift

flatmap

When I use flatMap with String type array it didn't give any warning, while it gives warning in case of Int type array. Why? Example:

let strings = [
    "I'm excited about #SwiftUI",
    "#Combine looks cool too",
    "This year's #WWDC was amazing"
]
strings.flatMap{$0 + "."} //No warning

let ints = [
   2,3,4
]
ints.flatMap{$0 + 1} //'flatMap' is deprecated: Please use compactMap(_:) for the case where closure returns an optional value
like image 398
Muneesh Chauhan Avatar asked Jan 26 '23 18:01

Muneesh Chauhan


1 Answers

It is because these are two different flatMap methods.

So, before I answer your question, let’s step back and consider what flatMap is now intended to do, namely, applying transform to a sequence and concatenating the resulting sequences. The typical example is used for “flattening” arrays of arrays):

let arrayOfArrays = [[1, 2], [3, 4, 5]]
let array = arrayOfArrays.flatMap { $0 }
print(array)

Resulting in:

[1, 2, 3, 4, 5]

The flatMap has flattened the array of arrays to a single array.

Confusingly, there was another, now deprecated, flatMap that would perform the transform, unwrapping optional results in a sequence or collection, but removing those that were nil. Fortunately, that has now been renamed to compactMap to avoid confusion. So, this is why you got your warning.

Consider:

let input: [Int?] = [0, 1, nil, 3]
let results = input.flatMap { $0 } // 'flatMap' is deprecated: Please use compactMap(_:) for the case where closure returns an optional value
print(results)

Resulting in:

[0, 1, 3]

So, we should replace flatMap with compactMap, as advised:

let input: [Int?] = [0, 1, nil, 3]
let results = input.compactMap { $0 }
print(results)

That will give us the desired results, without the warning.


So, let’s go back to your examples. Because strings are arrays of characters, it will take you at your word and flatten that down:

let strings = [
    "I'm excited about #SwiftUI",
    "#Combine looks cool too",
    "This year's #WWDC was amazing"
]
let stringResults = strings.flatMap { $0 + "." }
print(stringResults)

The result of that is a flattened array of characters:

["I", "\'", "m", " ", "e", "x", "c", "i", "t", "e", "d", " ", "a", "b", "o", "u", "t", " ", "#", "S", "w", "i", "f", "t", "U", "I", ".", "#", "C", "o", "m", "b", "i", "n", "e", " ", "l", "o", "o", "k", "s", " ", "c", "o", "o", "l", " ", "t", "o", "o", ".", "T", "h", "i", "s", " ", "y", "e", "a", "r", "\'", "s", " ", "#", "W", "W", "D", "C", " ", "w", "a", "s", " ", "a", "m", "a", "z", "i", "n", "g", "."]

That obviously not what you intended, but the compiler took you at your word that you wanted to flatten the array of array of characters (i.e. the array of strings) into a flat array of characters. So that’s why there was no warning.


Needless to say, in your examples, you would use neither flatMap (because you aren’t dealing with arrays of arrays) nor compactMap (because you aren’t dealing with optionals). You’d just use map:

let strings = [
    "I'm excited about #SwiftUI",
    "#Combine looks cool too",
    "This year's #WWDC was amazing"
]
let stringsResults = strings.map { $0 + "." }
print(stringsResults)

let ints = [2, 3, 4]
let intsResults = ints.map { $0 + 1 }
print(intsResults)

Completely unrelated, but in the interest of full disclosure (but at the risk of making it even more confusing), there is actually yet another flatMap method (!), one on the Optional type. Admittedly, this is arguable used less commonly than the array flattening (i.e. sequence concatenating) rendition, but I should probably acknowledge its existence.

This flatMap method on Optional “Evaluates the given closure when this Optional instance is not nil, passing the unwrapped value as a parameter.” But if the optional was nil, this flatMap will return nil, too.

For example:

func message(for value: Int?) -> String? {
    return value.flatMap { "The value is \($0)" }
}

Thus, if value was 42, result would be the optional string, "The value is 42". But if value was nil, then result will be nil.

This rendition of flatMap is not relevant to the question at hand, but I wanted to mention it for the sake of completeness.

like image 150
Rob Avatar answered Feb 08 '23 18:02

Rob