Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

swift if case and optional binding

Tags:

swift

what is the difference between the three code blocks below?

  1. optional binding
let someInt: Int? = 42
if let x = someInt {
  print(x)
}
  1. enum case pattern
let someInt: Int? = 42
if case .some(let x) = someInt {
  print(x)
}
  1. optional case pattern
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.

like image 602
mrd2242 Avatar asked Mar 29 '26 23:03

mrd2242


1 Answers

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 an Optional<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.

like image 66
Sweeper Avatar answered Apr 02 '26 13:04

Sweeper