Hopefully by the title of this, it's clear I'm not asking does Swift support the Switch statement. I'm specifically asking if Swift supports Switch expressions, akin to what C# has.
The difference is subtle, but important. A Switch statement is a way to group lines of code based on a particular case. A Switch expression however returns a value based on a particular case.
Say you have the following enum...
enum SomeEnum {
case a
case b
case c
}
Now say you need to calculate/return some value based on the particular switch statement. Currently, in Swift you have to use a Switch statement to do this...
let someEnumValue: SomeEnum = .a
let result: String
switch someEnumValue {
case .binary: result = "This is the 'A' type"
case .octal: result = "This is the 'B' type"
case .hexadecimal: result = "This is the 'C' type"
}
print(result)
//prints 'This is the 'A' type'
As you see above, in Swift, you have to first declare let result: String
but not give it a value, then within the Switch statement, you have to assign the value there. This is because a Switch statement doesn't return a value. It only executes code based on the matching case/condition. (Yes, you could also put all that in a function and simply call that, but that's separate from this question.)
C# Switch Expression
In contrast, here's how you would write it in C# with a Switch expression...
var result = someEnum switch {
SomeEnum.a => "This is the 'A' type",
SomeEnum.b => "This is the 'B' type",
SomeEnum.c => "This is the 'C' type"
}
Console.WriteLine(result)
//prints 'This is the 'A' type'
As you can see here, the Switch expression directly assigned a value to the result
variable since a Switch expression returns a value.
Of note: Unlike with a Switch statement where the word 'switch' goes before the variable, in a Switch expression, the word switch goes after the variable. Additionally, within the braces, the individual cases are separated by commas. Finally, every case can only be a single expression that produces a value. You can't run compound statements unless you first wrap them in their own function.
Pseudo version with Closures
A colleague of mine came up with this approach which uses an in-place closure. It's a little better, but still not quite as simple as a true Switch expression...
let result = {
switch someEnum {
case .a: return "This is the 'A' type"
case .b: return "This is the 'B' type"
case .c: return "This is the 'C' type"
}
}()
print(result)
So my question is simple... does Swift support Switch expressions? If not, let's all suggest it to Swift.org because it makes things so much easier/simpler!
CodePudding user response:
Unfortunately, Swift does not have switch
expressions, only switch
statements. The Swift language grammar currently supports the following as expressions:
- References to identifiers
- Literals
- Self expressions (
self.<whatever>
,self[<whatever>]
, etc.) - Superclass expressions (
super.<whatever>
,super[<whatever>]
, etc.) - Closures
- Parenthesized expressions (expressions, in parentheses)
- Tuples
- Implicit member expressions (references to functions or variables that would reference
self
, but based on context, are allowed to skip referencingself
— e.g.foo(123)
as opposed toself.foo(123)
) - Wildcards (
_
) - Key paths, selectors, and key path strings
Note that things like control flow statements, do
statements, and others are not included in this list — Swift only allows those as full statements. Currently, statements can be composed of:
- Expressions
- Declarations
- Loop statements
- Branch statements (
if
/guard
/switch
) - Labeled statements (
label: <some statement>
) - Control transfer statements (
break
,continue
, etc.) - Defer statements
- Do statements
- Compiler control statements (
#if ...
,#error
,#warning
, etc.)
This is something currently intimately tied to the core of the language, so changing it would be no small feat! For this reason, this feature is also at the top of the list of the Swift "commonly rejected changes" list for control flow:
if
/else
andswitch
as expressions: 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. Making them expressions introduces significant tradeoffs, and on balance, we haven't found a design that is clearly better than what we have so far.
Despite this, this is something that comes up periodically on the forums, and has been discussed extensively (e.g. If / else expressions, which contains a lot of discussion of switch
expressions too). This is something that plenty of folks want, so I'd recommend getting an understanding the latest state of things by reading through some of the threads on the forums for ideas on what/how to constructively propose, if you're interested!