# Challenge: Flattening nested optionals

**URL:** <https://forums.swift.org/t/challenge-flattening-nested-optionals/24083>\
**Category:** Using Swift\
**Created:** [May 3, 2019, 3:38am UTC](https://forums.swift.org/t/challenge-flattening-nested-optionals/24083 "2019-05-03T03:38:46Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Nevin](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/nevin/32/617_2.png) [@Nevin](https://forums.swift.org/u/Nevin)\
**Post date:** [May 3, 2019, 3:38am UTC](https://forums.swift.org/t/challenge-flattening-nested-optionals/24083/1 "2019-05-03T03:38:46Z")

</div>

Here’s a little programming puzzle:

Can you write a Swift function that will flatten any arbitrary `Optional`, no matter how deeply nested, down to a single level of optionality?

That is, the function accepts an `Optional`, determines whether the deepest inhabited layer contains `nil` or a non-`Optional` value, and returns the result as a single `Optional` without any nesting.

In particular, it should work without knowing what type is ultimately wrapped at the bottom of the pile, and it should even work if the outermost type is an `Any?` hiding unknown additional `Optionals` inside.

---

<div class="post-metadata">

**Author:** ![aemino](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/aemino/32/5291_2.png) [@aemino](https://forums.swift.org/u/aemino)\
**Post date:** [May 3, 2019, 6:23am UTC](https://forums.swift.org/t/challenge-flattening-nested-optionals/24083/2 "2019-05-03T06:23:20Z")

</div>

```swift
func flatten(_ opt: Any?) -> Any? {
  guard let unwrapped = opt else {
    return nil
  }

  if Mirror(reflecting: unwrapped).displayStyle == .optional {
    return flatten(Mirror(reflecting: unwrapped).children.first!.value)
  } else {
    return Optional(unwrapped)
  }
}

```

I think this will do it. I feel a bit dirty after writing this, but hey, it seems to do the job. Let me know if it does/doesn't work, it's late and I'm going to go to bed now. 🙂

I ended up using Mirror to avoid having to create a protocol, but a protocol-based solution may be more desirable if you want "vanilla" Swift code. Perhaps there exists a way to do this without either caveat!

---

<div class="post-metadata">

**Author:** ![gwendal.roue](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/gwendal.roue/32/13992_2.png) [@gwendal.roue](https://forums.swift.org/u/gwendal.roue)\
**Post date:** [May 3, 2019, 6:29am UTC](https://forums.swift.org/t/challenge-flattening-nested-optionals/24083/3 "2019-05-03T06:29:00Z")

</div>

Another try:

```swift
private protocol _OptionalProtocol {
    var _deepUnwrapped: Any? { get }
}
extension Optional: _OptionalProtocol {
    fileprivate var _deepUnwrapped: Any? {
        if let wrapped = self { return deepUnwrap(wrapped) }
        return nil
    }
}
func deepUnwrap(_ any: Any) -> Any? {
    if let optional = any as? _OptionalProtocol {
        return optional._deepUnwrapped
    }
    return any
}

deepUnwrap(1) // 1
deepUnwrap(Optional<Int>.none) // nil
deepUnwrap(Optional<Int>.some(1)) // 1
deepUnwrap(Optional<Optional<Int>>.none) // nil
deepUnwrap(Optional<Optional<Int>>.some(Optional<Int>.none)) // nil
deepUnwrap(Optional<Optional<Int>>.some(Optional<Int>.some(1))) // 1

```

---

<div class="post-metadata">

**Author:** ![Nevin](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/nevin/32/617_2.png) [@Nevin](https://forums.swift.org/u/Nevin)\
**Post date:** [May 3, 2019, 2:22pm UTC](https://forums.swift.org/t/challenge-flattening-nested-optionals/24083/4 "2019-05-03T14:22:22Z")

</div>

Well done, that was quick!

I posted this puzzle because I only just figured out how to do it yesterday, after having previously tried unsuccessfully some months ago.

The solution I had in mind is very similar to @gwendal.roue’s, though singly-recursive rather than bouncing between two functions:

```swift
protocol Flattenable {
  func flattened() -> Any?
}

extension Optional: Flattenable {
  func flattened() -> Any? {
    switch self {
    case .some(let x as Flattenable): return x.flattened()
    case .some(let x): return x
    case .none: return nil
    }
  }
}

```

---

<div class="post-metadata">

**Author:** ![jrose](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jrose/32/408_2.png) [@jrose](https://forums.swift.org/u/jrose)\
**Post date:** [May 3, 2019, 3:29pm UTC](https://forums.swift.org/t/challenge-flattening-nested-optionals/24083/5 "2019-05-03T15:29:56Z")

</div>

Can I ask why you'd _want_ to do this? Is it not possible to flatten each level as you go?

---

<div class="post-metadata">

**Author:** ![young](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/young/32/7878_2.png) [@young](https://forums.swift.org/u/young)\
**Post date:** [May 5, 2019, 5:07am UTC](https://forums.swift.org/t/challenge-flattening-nested-optionals/24083/6 "2019-05-05T05:07:12Z")

</div>

This seems to work:

```
let nestedOptional = Optional<Optional<Optional<Int>>>.some(Optional<Int>.some(1))

let unwrapped = nestedOptional.flatMap { $0! }

```

unwrapped is Optional(1)

---

<div class="post-metadata">

**Author:** ![Jens](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jens/32/12903_2.png) [@Jens](https://forums.swift.org/u/Jens)\
**Post date:** [May 5, 2019, 8:26am UTC](https://forums.swift.org/t/challenge-flattening-nested-optionals/24083/7 "2019-05-05T08:26:57Z")

</div>

> [@young](#):
>
> ```swift
> let nestedOptional = Optional<Optional<Optional<Int>>>.some(Optional<Int>.some(1))
> let unwrapped = nestedOptional.flatMap { $0! }
> 
> ```

Unless I'm mistaken, that's equivalent to:

```swift
let nestedOptional: Int??? = 1
let unwrapped = nestedOptional.flatMap { $0! }
print(type(of: unwrapped)) // Optional<Int>

```

And it only works for 2 and 3 levels of optionality, ie it doesn't do what the OP asked for ("flatten any arbitrary Optional, no matter how deeply nested, down to a single level of optionality"):

```swift
let nestedOptional1: Int?? = 1
let nestedOptional2: Int??? = 1
let nestedOptional3: Int???? = 1
let nestedOptional4: Int????? = 1
let unwrapped1 = nestedOptional1.flatMap { $0! }
let unwrapped2 = nestedOptional2.flatMap { $0! }
let unwrapped3 = nestedOptional3.flatMap { $0! }
let unwrapped4 = nestedOptional4.flatMap { $0! }
print(type(of: unwrapped1)) // Optional<Int>
print(type(of: unwrapped2)) // Optional<Int>
print(type(of: unwrapped3)) // Optional<Optional<Int>>
print(type(of: unwrapped4)) // Optional<Optional<Optional<Int>>>

```

Also, for a single level of optionality

```swift
let nestedOptional0: Int? = 1

```

the expression won't compile:

```swift
let unwrapped0 = nestedOptional0.flatMap { $0! } // ERROR: Cannot force unwrap value of non-optional type 'Int'

```

---

<div class="post-metadata">

**Author:** ![Jens](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jens/32/12903_2.png) [@Jens](https://forums.swift.org/u/Jens)\
**Post date:** [May 5, 2019, 12:24pm UTC](https://forums.swift.org/t/challenge-flattening-nested-optionals/24083/8 "2019-05-05T12:24:23Z")

</div>

May I present this non-recursive solution which doesn't erase the type (but still works for `Any?`):

```swift
func funwrap<T>(_ v: T????????????????????) -> T? {
    return (v as? T?) ?? nil
}

```

It works for 0 through 20 levels of optionality.

Adding more than 20 gets hard on the type checker, and the following demonstration program will take 15 seconds to compile on my machine:

```swift
func funwrap<T>(_ v: T????????????????????) -> T? {
    return (v as? T?) ?? nil
}

let v0: Int = 0
let v1: Int? = nil
let v2: Int?? = 2
let v3: Int??? = nil
let v4: Int???? = 4
let v5: Int????? = nil
let v20: Int???????????????????? = 20

let result: [Int?] = [ funwrap(v0), funwrap(v1), funwrap(v2), funwrap(v3),
    funwrap(v4), funwrap(v5), funwrap(v20) ]

print(result)

```

* * *

```swift
$ time swiftc demo.swift
real 0m15.087s
user 0m14.762s
sys 0m0.270s
$ ./demo
[Optional(0), nil, Optional(2), nil, Optional(4), nil, Optional(20)]

```

* * *

But isn't the simplest solution to just use `as? T?` directly, like this:

```swift
// Here, v can have any level of optionality, although there will be a warning
// when flattening if the level is 0, 1 or 2:
let v: Int??????????????????????????????????????????????????????????? = 123
let flattenedToOneLevelOfOptionality = (v as? Int?) ?? nil

print(type(of: flattenedToOneLevelOfOptionality)) // Always prints Optional<Int>
dump(flattenedToOneLevelOfOptionality)

```

---

<div class="post-metadata">

**Author:** ![michelf](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/michelf/32/1180_2.png) [@michelf](https://forums.swift.org/u/michelf)\
**Post date:** [May 5, 2019, 1:11pm UTC](https://forums.swift.org/t/challenge-flattening-nested-optionals/24083/9 "2019-05-05T13:11:40Z")

</div>

> [@Jens](#):
>
> But isn't the simplest solution to just use `as? T?` directly

`v as? Int` is even simpler:

```swift
let v: Int??????????????????????????????????????????????????????????? = 123
let flattenedToOneLevelOfOptionality = v as? Int

```

---

<div class="post-metadata">

**Author:** ![Jens](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jens/32/12903_2.png) [@Jens](https://forums.swift.org/u/Jens)\
**Post date:** [May 5, 2019, 1:20pm UTC](https://forums.swift.org/t/challenge-flattening-nested-optionals/24083/10 "2019-05-05T13:20:52Z")

</div>

Ah, of course! 🤦‍♂️ So my "solution" (which is really just an unnecessary wrapper around `as?`) can be simplified into:

```swift
func funwrap<T>(_ v: T????????????????????) -> T? {
    return (v as? T)
}

```

It would be interesting to know if it is possible to rewrite this function (still non-recursively) so that it works for any level of optionality, ie not just 0 through 20, but 0 and more.

---

<div class="post-metadata">

**Author:** ![Nevin](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/nevin/32/617_2.png) [@Nevin](https://forums.swift.org/u/Nevin)\
**Post date:** [May 5, 2019, 2:06pm UTC](https://forums.swift.org/t/challenge-flattening-nested-optionals/24083/11 "2019-05-05T14:06:09Z")

</div>

> [@Jens](#):
>
> ```swift
> func funwrap<T>(_ v: T????????????????????) -> T? {
> return (v as? T)
> }
> 
> ```

In additional to be being limited by the number of question marks you write in the function definition, that also breaks down when `Any` is involved, by actually _increasing_ the optionality up to the number of question marks:

```swift
let x: Any? = 0
let y = funwrap(x)
print(y.debugDescription)
// Optional(Optional(Optional(Optional(Optional(Optional(Optional(Optional(Optional(Optional(
// Optional(Optional(Optional(Optional(Optional(Optional(Optional(Optional(Optional(Optional(
// Optional(0)))))))))))))))))))))

```

---

<div class="post-metadata">

**Author:** ![Jens](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jens/32/12903_2.png) [@Jens](https://forums.swift.org/u/Jens)\
**Post date:** [May 5, 2019, 2:16pm UTC](https://forums.swift.org/t/challenge-flattening-nested-optionals/24083/12 "2019-05-05T14:16:34Z")

</div>

You're right. I'm _almost_ sure that I did double check that it worked for `Any` ... : P

---

<div class="post-metadata">

**Author:** ![Nevin](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/nevin/32/617_2.png) [@Nevin](https://forums.swift.org/u/Nevin)\
**Post date:** [May 7, 2019, 4:54pm UTC](https://forums.swift.org/t/challenge-flattening-nested-optionals/24083/13 "2019-05-07T16:54:31Z")

</div>

> [@jrose](#):
>
> Can I ask why you'd _want_ to do this? Is it not possible to flatten each level as you go?

Well, some people seem to think it’s a good idea to work with constructs like [a dictionary of `AnyKeyPath`s to optional properties](https://forums.swift.org/t/unexpected-return-type-from-keypath-subscript/24239). I don’t personally vouch for that design, but it apparently exists.

Mostly I just wanted to see if I could, and it wasn’t immediately obvious how to test whether an `Any` is actually an `Optional` for recursive unwrapping.

What is more difficult, is to programmatically identify the bottom-most `Wrapped` type in an arbitrary stack of `Optional`s that includes `Any?`, especially if some layer other than the innermost is actually `.none`.

---

<div class="post-metadata">

**Author:** ![Peter-Schorn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/peter-schorn/32/11183_2.png) [@Peter-Schorn](https://forums.swift.org/u/Peter-Schorn)\
**Post date:** [July 2, 2020, 3:26am UTC](https://forums.swift.org/t/challenge-flattening-nested-optionals/24083/14 "2020-07-02T03:26:33Z")

</div>

To me, the reason why you want want to do this is simple: Nested optionals are almost never useful, but they do arise sometimes due to quirks of the language (such as accessing a value from a dictionary for which the type of its values are Optional); therefore it's nice to have a function to call to flatten them to a single optional in one step. And could you elaborate on what you mean by "flatten each level as you go?" I'm not sure I understand.

---

<div class="post-metadata">

**Author:** ![Peter-Schorn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/peter-schorn/32/11183_2.png) [@Peter-Schorn](https://forums.swift.org/u/Peter-Schorn)\
**Post date:** [July 2, 2020, 4:18am UTC](https://forums.swift.org/t/challenge-flattening-nested-optionals/24083/15 "2020-07-02T04:18:53Z")

</div>

Has anyone figured out how to do this without casting the result to `Any?`? Is there some way preserve the type of the underlying value by using generics?

---

<div class="post-metadata">

**Author:** ![Lantua](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/lantua/32/8868_2.png) [@Lantua](https://forums.swift.org/u/Lantua)\
**Post date:** [July 2, 2020, 4:31am UTC](https://forums.swift.org/t/challenge-flattening-nested-optionals/24083/16 "2020-07-02T04:31:02Z")

</div>

> [@Peter-Schorn](#):
>
> but they do arise sometimes due to quirks of the language (such as accessing a value from a dictionary for which the type of its values are Optional)

It’s actually cases like this that I’d suggest unwrapping things layer by layer. There’s a distinction between not having any value (outer optional) and having the value that is `nil` (inner optional). There’s really no point in making value type optional if it doesn’t

So one should unwrap the first layer to see if it has value at all, then unwrap the second layer to see if the stored value is `nil`.

Nonetheless, if you **already know** the bottom type those optionals are wrapping, this thread doesn’t really apply and you can just use `as?`.

---

<div class="post-metadata">

**Author:** ![wowbagger](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/wowbagger/32/13847_2.png) [@wowbagger](https://forums.swift.org/u/wowbagger)\
**Post date:** [July 2, 2020, 4:48am UTC](https://forums.swift.org/t/challenge-flattening-nested-optionals/24083/17 "2020-07-02T04:48:32Z")

</div>

> [@Lantua](#):
>
> > [@Peter-Schorn](#):
> >
> > but they do arise sometimes due to quirks of the language (such as accessing a value from a dictionary for which the type of its values are Optional)
> 
> It’s actually cases like this that I’d suggest unwrapping things layer by layer. There’s a distinction between not having any value (outer optional) and having the value that is `nil` (inner optional).

Is it possible for an `Optional` equivalent of the nested `Slice<Slice<Slice<...>>>` situation to occur naturally from some recursive function call, and render this exhaustive flattening useful?

---

<div class="post-metadata">

**Author:** ![Peter-Schorn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/peter-schorn/32/11183_2.png) [@Peter-Schorn](https://forums.swift.org/u/Peter-Schorn)\
**Post date:** [July 2, 2020, 4:53am UTC](https://forums.swift.org/t/challenge-flattening-nested-optionals/24083/18 "2020-07-02T04:53:47Z")

</div>

> [@Lantua](#):
>
> So one should unwrap the first layer to see if it has value at all, then unwrap the second layer to see if the stored value is `nil` .

That will work when you have a double-wrapped optional, of course, but that was just one example meant do demonstrate a broader point: Suppose you have a triple-wrapped optional—or a quadruple-wrapped optional—and you want do find out if the innermost value is nil. You would have to write _more_ code for each additional layer of optionality. This kind of redundancy is a code smell to me.

> [@Lantua](#):
>
> There’s a distinction between not having any value (outer optional) and having the value that is `nil` (inner optional).

Of course there is a difference between an optional, a double-wrapped optional, a triple-wrapped optional, and so on. They're all different types. For some cases that difference matters, so I fully understand why swift doesn't implicitly remove the extra layers of optionality, but in other cases, the difference does not matter and it would be nice to have a single function that removes all the extra layers of optionality.

> [@Lantua](#):
>
> Nonetheless, if you **already know** the bottom type those optionals are wrapping, this thread doesn’t really apply and you can just use `as?` .

True, but I'm looking for a function that would work for any bottom type and that doesn't cast the result to `Any?`.

---

<div class="post-metadata">

**Author:** ![Peter-Schorn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/peter-schorn/32/11183_2.png) [@Peter-Schorn](https://forums.swift.org/u/Peter-Schorn)\
**Post date:** [July 2, 2020, 5:22am UTC](https://forums.swift.org/t/challenge-flattening-nested-optionals/24083/19 "2020-07-02T05:22:36Z")

</div>

> [@wowbagger](#):
>
> Is it possible for an `Optional` equivalent of the nested `Slice<Slice<Slice<...>>>` situation to occur naturally from some recursive function call, and render this exhaustive flattening useful?

I'm not sure what you're referring to.

---

<div class="post-metadata">

**Author:** ![Lantua](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/lantua/32/8868_2.png) [@Lantua](https://forums.swift.org/u/Lantua)\
**Post date:** [July 2, 2020, 11:24am UTC](https://forums.swift.org/t/challenge-flattening-nested-optionals/24083/20 "2020-07-02T11:24:15Z")

</div>

> [@Peter-Schorn](#):
>
> You would have to write _more_ code for each additional layer of optionality.

To me, not handle each layer of optionality that appears explicitly is also a big code smell. It’s not like you keep wrapping each optional layer for the sake of it. And as I said, if you know the target type, just use `as?`. I haven’t even mentioned `Any?` anywhere.

> [@Peter-Schorn](#):
>
> True, but I'm looking for a function that would work for any bottom type and that doesn't cast the result to `Any?` .

What are you trying to do? The OP of this thread wants it to work with `Any` as an outer type. You already lose a lot of type information whether you cast it to `Any?` or not.

> [@wowbagger](#):
>
> Is it possible for an `Optional` equivalent of the nested `Slice<Slice<Slice<...>>>` situation to occur naturally from some recursive function call, and render this exhaustive flattening useful?

Perhaps it is. The main difference with optional is that it does mean different things at different places. Even then, you wouldn’t see a lot of deeply nested optionals (or slices, for that matter) in recursive functions.

[Next page](https://forums.swift.org/t/challenge-flattening-nested-optionals/24083.md?page=2)
