Swift: Grokking Map, flatMap, and compactMap

Milan Brankovic
The Startup
4 min readJul 19, 2020

--

Swift borrows many functional programming concepts, among others: map, flatMap and compactMap. This article will give a closer look at these operations.

map

Suppose that we have detectives with: name, rank and cases working on. To find out which detectives are heavily involved in solving cases we can implement the following approach

This is a good start, but it can be improved with map operation. With map you can transform each value of the array into something that is desirable. map receives a closure which gets called for each element of the array. After it finishes it returns a new mapped array.

This looks pretty good, and can be extended even more. The result of map can be put into pipeline to perform additional transformations. Imagine that we need to get the names of detectives who are not involved in any case in order to assign them some. We can accomplish this by creating a following construct:

A pipeline defines a clear and immutable way of transforming data into separate steps. Generally, a pipeline is performant enough and worth the expressive and immutable nature.

An Array is not the only collection type which you can use map over. You can use any Collection and Sequence protocol implementation as well as Optionals.

flatMap

The flatMap function is similar to map except that it “flattens” the resulting array. With map you can end up with nested type, flatMap is there to handle this case. The example below shows detective's scores on each test, and we want to check if the average result is higher than some threshold value:

So map transforms an array of values into an array of other values, and flatMap does the same thing, but also flattens the result of nested collections into just a single array.

compactMap

Finally, there’s compactMap, which lets us discard any nil values that our transform might produce. Instead of flattening nested collection, this function performs flattening optionals inside the collection.

Let's go over an example that will shine a light on this type of operation. A user is providing a list of his/hers favorite websites, which we are trying to reach from code. We will try to turn passed strings into URLs and then perform operation:

As construction of URL can fail and return nil, map would not produce correct output (it will contain nil). Additionally, map would produce elements wrapped in Optional which should be handled. compactMap takes care of both problems for us.

As for map, both flatMap and compactMap can be chained (used in pipeline).

Key takeaways

  • map transforms an array of values into an array of other values
  • flatMap does the same thing, but also flattens the result of nested collections into just a single array
  • when an Optional is nil, map and flatMap will ignore any chained operations
  • with compactMap you can filter nil values out of arrays and sequences of Optionals
  • everything can be done in imperative way as well
  • if you are considering performance as a key factor, you should test both imperative and functional way in order to tailor the code to your needs

--

--