Why does optional binding allow multiple levels of optionality?

I may try, using our if let y = x.first example.

Array.first is documented as "If the collection is empty, the value of this property is nil".

OK, so we can build as isEmpty function which accepts any array and uses first in order to compute its result:

func isEmpty<T>(_ x: [T]) -> Bool {
    if let y = x.first { return false } else { return true }
}

And we expect isEmpty to return false for [nil, 1, 2]:

let x: [Int?] = [nil, 1, 2]
let result = isEmpty(x)
print(result) // false

Do you agree so far?

And if we replace isEmpty with its implementation, we get:

let x: [Int?] = [nil, 1, 2]
let result: Bool
if let y = x.first { result = false } else { result = true }
print(result) // still false (and y was set nil)

Conclusion: according to this story, we could say that the "why" is "support for generic programming, where an array of Int? is processed in the same way as an array of Int, String, or URL?". Emptiness, and having a first element or not, do not depend on the type of the elements.

There are other parts of the language where optionals are squashed together. For example, take try?:

func foo() throws -> Int? { ... }
let y = try foo()  // Int?
let y = try? foo() // Int? as well

So yes you'll find that the language is not 100% regular. Yet if let a = b peals only one level of optionality, that's for sure.

3 Likes