iOS User
iOS User

Reputation: 91

Advanced pattern matching swift

Is there way to use optionals in switch-case branches? For example: some function f(arg:) returns String?. We require to perform some switch-case branch when f(arg:) returns non‑nil value, and use this value. See the following example.

func f(arg: Int) -> String?

let someValue: Int = ...

switch someValue {
    case -3, -2, -1:
        print("error: negative")
    case 10, 11, 12:
        print("error: too big")
    case let value, let str = f(arg: value): // HOW ????
        print("success: non-nil string \(str)")
    default:
        print("fail")    
}

Upvotes: 0

Views: 724

Answers (2)

Gusutafu
Gusutafu

Reputation: 755

Old one but this is probably what you want:

func f(arg: Int) -> String?

let someValue: Int = ...

switch (someValue, f(arg: value)) {
    case (-3 ... -1, _):
        print("error: negative")
    case (10...12, _):
        print("error: too big")
    case (_, let str?):
        print("success: non-nil string \(str)")
    default:
        print("fail")    
}

Upvotes: 1

Code Different
Code Different

Reputation: 93161

I think your switch statement is equivalent to this:

switch someValue {
    case -3, -2, -1:
        print("error: negative")
    case 10, 11, 12:
        print("error: too big")
    default:
        if let str = f(arg: someValue) {
            print("success: non-nil string \(str)")
        } else {
            print("fail")
        }
}

But a cleaner way to write that would be using a guard statement so you know that someValue is valid before passing it to the function:

guard case 0...9 = someValue else {
    print("someValue is outside of valid range")
    // Handle error
    return
}

if let str = f(arg: someValue) {
    print("success: non-nil string \(str)")
} else {
    print("fail")
}

Another alternative is to simply make f returns nil if the argument is not in the expected range:

func f(arg: Int) -> String? {
    guard case 0...9 = arg else {
        print("\(arg) is not in the valid range of 0...9")
        return nil
    }

    // ...
}

if let str = f(arg: someValue) {
    print("success: non-nil string \(str)")
} else {
    print("fail")
}

Upvotes: 2

Related Questions