what is the difference between the three code blocks below?
let someInt: Int? = 42
if let x = someInt {
print(x)
}
let someInt: Int? = 42
if case .some(let x) = someInt {
print(x)
}
let someInt: Int? = 42
if case let x? = someInt {
print(x)
}
Why a so simple functionality need 3 different syntax? It make the language too confusing!
And why the code below doesn't work?
let someInt: Int? = 42
var x: Int?
if case x? = someInt {
print(x)
}
I just want to say, so damn confusing the language is.
The first three code snippets you showed are the same. Out of the three, the first (optional binding) is definitely the recommended way to bind an optional in an if statement, as recommended by the Swift Guide:
You use optional binding to find out whether an optional contains a value, and if so, to make that value available as a temporary constant or variable.
The other two ways, I feel, are a bit more roundabout. Why would you write x + 2 - 1 when you can just write x + 1?
The enum case pattern works because Optional being implemented as an enum.
According to the Swift Reference, the optional pattern is just a syntactic sugar for the enum case pattern for the special case of Optional:
An optional pattern matches values wrapped in a
some(Wrapped)case of anOptional<Wrapped>enumeration.
OTOH, there are times when you can't use optional binding, such as in a for loop or a switch statement. These are the times when optional patterns come in handy. An example from the Swift Reference:
let arrayOfOptionalInts: [Int?] = [nil, 2, 3, nil, 5]
// Match only non-nil values.
for case let number? in arrayOfOptionalInts {
print("Found a \(number)")
}
If you have a look at the syntax of the control flow statements and loops, you'll notice that patterns can be used in a lot more places than optional binding. Enum case patterns and optional patterns are patterns, but optional binding isn't a pattern.
The fourth code snippet prints nothing, because Optional.some(42) does not match the pattern x?. Recall what an optional pattern matches, it matches .some(x). x is nil (you haven't initialised it to anything), so you are matching .some(42) to .some(.none). Clearly they don't match, so the if statement does not run. Even if it did run, printing x would give you nil, as this is pattern matching, not variable assignment. If you want to do something similar to assigning variables...
You'd need to use a value binding pattern like let x? in cases like this. The optional pattern expands to let .some(x), and,
Identifiers patterns within a value-binding pattern bind new named variables or constants to their matching values.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With