Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to bind a variable to multiple alternatives in a switch statement?

Tags:

swift

Suppose I have an enum definition as follows:

enum Response {
    case Result(String, Int)
    case Error(String)
}

Then, I get such a response:

let resp: Response = // ...

Suppose I want to write a switch statement and handle the same way the Result and the Error cases and bind a variable of the same name to the String they contain. How can I do this? Conceptually, something similar to this:

switch resp {
    case let .Result(str, _), let .Error(str):
        println("Found: \(str)")
}

where str is bound twice, and _ signals that I'm not interested in the Int value that a Result carries.

So far, the closest thing I could find was to declare an inline function like this and then call it:

func processRespString(str: String) {
    println("Found \(str)")
}

switch resp {
    case let .Result(str, _): processRespString(str)
    case let .Error(str): processRespString(str)
}

Is there a better way?

like image 801
Jean-Philippe Pellet Avatar asked Jun 02 '14 23:06

Jean-Philippe Pellet


2 Answers

The Swift evolution Proposal SE-0043 that has been accepted fixed this issue with Swift 3.

enum Response {
    case result(String, Int)
    case error(String)
}

let resp = Response.error("Some text")

switch resp {
case let .result(str, _), let .error(str):
    print("Found: \(str)") // prints Found: Some text
}

With Swift 2, the previous Playground code would generate an error: case labels with multiple patterns cannot declare variables. However, with Swift 3, it generates no errors and has the expected behavior.

like image 114
Imanou Petit Avatar answered Sep 21 '22 20:09

Imanou Petit


No, but if you want to access the String value of a Response regardless of whether it is a .Result or an .Error, you can do this:

enum Response {
    case Result(String, Int)
    case Error(String)

    func Message() -> String {
        switch self {
            case let .Result(str, _):
                return str
            case let .Error(str):
                return str
        }
    }
}

var resp: Response = .Error("Fault")
resp = .Result("Success",5)

println(resp.Message())

This way you keep the logic for the enum inside the enum itself.

like image 43
kareman Avatar answered Sep 20 '22 20:09

kareman