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.