flatMap on optional - Purpose?

I just stumbled upon a usage of `flatMap` on optionals.

Code

``````var a : Int? = nil

let x = a.flatMap { _ in return 10 }

print("x = \(String(describing: x))")
``````

Output:

`x = nil`

if `a` is `nil`, then `flatMap` returns `nil` else it returns `10`

Question / Doubt:

I was just wondering if there a reason why `flatMap` exists for optionals because `map` does the same thing on optionals.

It does not do the same thing, but due to Swift automatically promoting values as needed to `Optional`s, youâ€™re seeing the same result.
The difference between `map` and `flatMap` is that the given transform in one case returns `T`, in the other `T?`.

A better snippet for your example would be

``````var a : Int? = nil

let x = a.flatMap { \$0 > 0 ? \$0 : nil }

print("x = \(String(describing: x))")
``````
1 Like

Thanks,

In your example if `a = 5` map returns `Optional(Optional(5))` while `flatMap` returns `Optional(5)`

That's right. Because `map`'s generic parameter in inferred as `Int?`, hence it returns `Int??`, while `flatMap`'s generic parameter is inferred as `Int` , hence it returns `Int?`.

``````func map<U>(_ transform: (Wrapped) throws -> U) rethrows -> U?
``````
``````var a : Int? = nil
let x = a.map { \$0 > 0 ? \$0 : nil } // U == Int? -> U? == Int??
``````

``````func flatMap<U>(_ transform: (Wrapped) throws -> U?) rethrows -> U?
``````
``````var a : Int? = nil
let x = a.flatMap { \$0 > 0 ? \$0 : nil } // U == Int -> U? == Int?
``````

In general, `map()` transforms each element to another type, leaving the outer wrapper type alone. On the other hand, `flatMap()` transforms each element to *the wrapper type* (with another element type), and then â€śflattensâ€ť all the results into a single wrapper.

Here is a summary of how they work for `Array`, `Optional`, and a generic wrapper type `W`:

`.map()` Input Transform Output
Array [T] T â†’ U [U]
Optional T? T â†’ U U?
Generic W<T> T â†’ U W<U>

`.flatMap()` Input Transform Output
Array [T] T â†’ [U] [U]
Optional T? T â†’ U? U?
Generic W<T> T â†’ W<U> W<U>
4 Likes

You can also say, in a more general way, that `map` maps `A -> B` to `F(A) -> F(B)`,
while `flatMap` maps `A -> F(B)` to `F(A) -> F(B)` :)

(In flatMap, flat is likely an allusion to the return type being left untransformed)

Thanks Nevin and Anthony,

Nevin: Is `map` and `flatMap` interchanged in the table you provided ?

For optionals in `flatMap` the transformation mentioned is `T â†’ U?`, but that seems more like `map`.

Am I missing something ?

I know this question is to Nevin, but I guess it wonâ€™t hurt if I answer since Iâ€™m here.

This is the `flatMap` signature for `Optional`:

``````func flatMap<U>(_ transform: (Wrapped) throws -> U?) rethrows -> U?
``````

It maps, like any other flatMap, `A -> F(B)` to `F(A) -> F(B)`

In the `flatMap` for `Optional<Wrapped>`, `A` == `Wrapped`, `F(B)` == `U?`, `F(A)` == `Wrapped?`.

So `A -> F(B)` to `F(A) -> F(B)` becomes `Wrapped -> U?` to `Wrapped? -> U?`

For map, the â€śtransformâ€ť is always `A -> B`. For flatMap, itâ€™s always `A -> F(B)`, as you see in Nevinâ€™s table.

Thanks Antony and others, the examples helped. I will try out more examples.