24 June 2015 2min read

The unexpected but convenience case of flatMap in Swift

Yesterday night I found myself reading this code in GitHub

    for dictionary in array {
-        if let interaction = Interaction(dictionary: dictionary) {
-            interactions.append(interaction)
-        }
-    }
+    interactions = array.flatMap { Interaction(dictionary: $0) }

I read the diff a couple of times but I couldn’t understand why flatMap was used to replace the original code. I said to myself that was too late to understand it and fell asleep.

But today I’ve seen the tab on Safari still opened and I decided to open a Playground to check what was going on, and finally I understood my confusion.

As I understand flatMap should just apply a function to the elements of the collection and flatten the result.

To give an example: Given a list of strings with multiple words:

["hello world", "bye bye world"]

And the function that separates a string into a list of words. If you use map you will receive a list of lists of strings.

[["hello", "world"], ["bye", "bye", "world"]]

You can then flatten that list one level to receive just a list of words:

["hello", "world", "bye", "bye", "world"]

flatMap is just the combination of those two functions.

If instead of a function that returns and Array, you map a function that returns an Optional you will receive and array of Optionals.

func maybeAString(param: String) -> String? {
   guard param.characters.count > 2 else { return nil }
   return param
}

["this will pass", "no"].map(maybeAString)
// [{Some "this will pass"}, None]

Applying flatMap I was expecting to receive and array of the actual values and nils. But in Swift flatMap actually gets rid of the nil.

["this will pass", "no"].flatMap(maybeAString)
// ["this will pass"]

It’s kind of combining map (to apply the function), flatten (to unwrap the optionals) and filter (to remove the nils). Maybe I’m completely wrong but in any case I think it’s a nice feature that we can ignore the nils after applying flatMap.

If you enjoyed this post

Continue reading