Keith Grout Keith Grout - 5 months ago 13
Swift Question

What does "case" mean without switch statement in Swift?

I ran into this code which is part of a Swift implementation of a linked list in the Swift Algorithm Club. Throughout the implementation the author uses

case let
following a while statement right before unwrapping an optional. I've never seen the case keyword used outside of the context of a switch statement, and I'm wondering what exactly it does? Does it somehow cast the
let next? = node.next
part to true or false, maybe depending on whether
next?
becomes nil or not?

public var last: Node? {
if var node = head {
while case let next? = node.next {
node = next
}
return node
} else {
return nil
}
}

Answer

This is the Optional Pattern. It tests and unwraps an Optional, executing the conditional only if the Optional is non-nil.

The keyword case is needed because it follows from the original switch...case syntax. The case tests a pattern and if it matches then the following statement is executed. In your example the let next? = node.next is the pattern. If the value is unwrapped and assigned then the case matches and your code is executed.

From the documentation:

Optional Pattern

An optional pattern matches values wrapped in a Some(Wrapped) case of an Optional or ImplicitlyUnwrappedOptional enumeration. Optional patterns consist of an identifier pattern followed immediately by a question mark and appear in the same places as enumeration case patterns.

Because optional patterns are syntactic sugar for Optional and ImplicitlyUnwrappedOptional enumeration case patterns, the following are equivalent:

let someOptional: Int? = 42
// Match using an enumeration case pattern
if case .Some(let x) = someOptional {
    print(x)
}

// Match using an optional pattern
if case let x? = someOptional {
    print(x)
}

The optional pattern provides a convenient way to iterate over an array of optional values in a for-in statement, executing the body of the loop only for non-nil elements.

let arrayOfOptionalInts: [Int?] = [nil, 2, 3, nil, 5]
// Match only non-nil values
for case let number? in arrayOfOptionalInts {
    print("Found a \(number)")
}
// Found a 2
// Found a 3
// Found a 5
Comments