Martin Cowie Martin Cowie - 5 months ago 17
Swift Question

Using "if let..." with many expressions

This idiom of Swift makes good sense

if let x = someDict[someKey] { ... }

However, what I really want is

if let x = someDict[someKey], y = someDict[someOtherKey] { ... }

As written this is not incorrect, but is this idea possible?


Update for Swift 1.2

Since Swift 1.2, if let allows unwrapping multiple optionals, so you can now just write this, as in your example:

if let x = someDict[someKey], y = someDict[someOtherKey] { … }

You can even interleave conditions such as:

if let x = someDict[someKey] where x == "value", y = someDict[someOtherKey] { … }

This used to be valid before Swift 1.2

Here's how you would do it without an ugly force-upwrapping:

switch (dict["a"], dict["b"]) {
case let (.Some(a), .Some(b)):
    println("no match")

Still pretty verbose, actually.

This works because an optional type of the form Type? is actually shorthand for Optional<Type>, which is an enum that looks roughly like this:

enum Optional<T> {
    case None
    case Some(T)

You can then use pattern matching as for any other enum.

Edit: I've seen people write helper functions like this one (sorry for the lack of attribution, I don't remember where I saw it):

func unwrap<A, B>(a: A?, b: B?) -> (A, B)? {
    switch (a, b) {
    case let (.Some(a), .Some(b)):
        return (a, b)
        return nil

Then you can keep using the if let construct, namely like this:

if let (a, b) = unwrap(dict["a"], dict["b"]) {
    println("match: \(a), \(b)")
} else {
    println("no match")