How to assign a variable in a Swift case statement
Asked Answered
L

5

41

This works but seems inefficient:

switch var1 {
case 1:
    string1 = "hello"
case 2:
    string1 = "there"
default:
    string1 = "world"
}

but

string1 = switch var1 { ...

throws an error. Is there a more efficient way to write the switch/case so that the assigned variable isn't listed redundantly in each line?

Thanks in advance!

Larry answered 14/1, 2016 at 22:11 Comment(5)
See also github.com/apple/swift-evolution/blob/master/…: There are currently no plans to make switch an expression.Zoi
@MartinR "These are conceptually interesting things to support, but many of the problems solved by making these into expressions are already solved in Swift in other ways" as dfri and Tom Harrington elegantly demonstrated.Larry
@Larry such a shame.. I miss you Kotlin!Oahu
I find this quite elegant in functional languages like F# or Elixir. However being able to do let bla: String without assigning something the compiler forces that every possible path assigns something.Noddle
@DepartamentoB Wow, awesome. I had no idea these languages existed. And that such a language with fault tolerance for embedded systems exists, I am dying to poke around in it. THANKS MUCHO 😊Larry
O
27

You could put your switch block in a function that returns a String object, and assign the return of this function to your variable string1:

func foo(var1: Int) -> String {
    switch var1 {
    case 1:
        return "hello"
    case 2:
        return "there"
    default:
        return "world"
    }
}

/* Example */
var var1 : Int = 1
var string1 : String = foo(var1) // "hello"
var1 = 2
string1 = foo(var1)              // "there"
var1 = 5000
string1 = foo(var1)              // "world"

Alternatively let string1 be a computed property (e.g. in some class), depending in the value of say var1, and place the switch block in the getter of this property. In a playground:

var var1 : Int
var string1 : String {
    switch var1 {
    case 1:
        return "hello"
    case 2:
        return "there"
    default:
        return "world"
    }
}

/* Example */
var1 = 1
print(string1) // hello
var1 = 2
print(string1) // there
var1 = 100
print(string1) // world

If used in a class, just skip the Example block above.

Obumbrate answered 14/1, 2016 at 22:18 Comment(0)
H
135

Put the switch in an anonymous closure, if you'll only use that code in one place.

string1 = {
    switch var1 {
    case 1:
        return "hello"
    case 2:
        return "there"
    default:
        return "hello"
    }
}()
Hochstetler answered 14/1, 2016 at 22:21 Comment(0)
O
27

You could put your switch block in a function that returns a String object, and assign the return of this function to your variable string1:

func foo(var1: Int) -> String {
    switch var1 {
    case 1:
        return "hello"
    case 2:
        return "there"
    default:
        return "world"
    }
}

/* Example */
var var1 : Int = 1
var string1 : String = foo(var1) // "hello"
var1 = 2
string1 = foo(var1)              // "there"
var1 = 5000
string1 = foo(var1)              // "world"

Alternatively let string1 be a computed property (e.g. in some class), depending in the value of say var1, and place the switch block in the getter of this property. In a playground:

var var1 : Int
var string1 : String {
    switch var1 {
    case 1:
        return "hello"
    case 2:
        return "there"
    default:
        return "world"
    }
}

/* Example */
var1 = 1
print(string1) // hello
var1 = 2
print(string1) // there
var1 = 100
print(string1) // world

If used in a class, just skip the Example block above.

Obumbrate answered 14/1, 2016 at 22:18 Comment(0)
A
7

💡Swift v5.9

Now you can directly assign the value from the switch/case expression like:

let result = switch range {
    case 0...30: "Low"
    case 31...50: "Medium"
    case 51...80: "Hight"
    default: "Other"
}
Aquiline answered 6/12, 2023 at 13:8 Comment(0)
H
2

Switch (and if) expressions were added to Swift 5.9, shipping with Xcode 15.

Example from Swift.org:

let anotherCharacter: Character = "a"
let message = switch anotherCharacter {
case "a":
    "The first letter of the Latin alphabet"
case "z":
    "The last letter of the Latin alphabet"
default:
    "Some other character"
}


print(message)
// Prints "The first letter of the Latin alphabet"
Helbonnas answered 30/8, 2023 at 17:26 Comment(0)
E
1

You could use a dictionary instead of a switch statement, which is more flexible as it allows you to add new values with little overhead:

let map = [1: "hello", 2: "there"]
value = map[var1] ?? "world"

Or, in a single statement, and by using the default subscript:

let value = [1: "hello", 
             2: "there"][var1, default: "world"]

The default argument passed to the subscript call works just like the default clause from the switch

Erleena answered 14/1, 2016 at 22:54 Comment(2)
This throws out the ability of the compiler to tell you that your switch statement does not cover all cases.Selfaggrandizement
Agreed, however using a default clause, like in the code the asker posted, has the same pitfall as you mentioned. Also the switch seems to be on an integer value, and an exhaustive switch for that is a little bit hard to write :)Erleena

© 2022 - 2024 — McMap. All rights reserved.