Lets say we have an enum with associated values:
enum A {
case a1(x: Int)
case a2(y: String)
}
And some function that switches on this enum:
func doSomething(a: A) {
switch a {
case .a1(let x):
print("a1 let \(x)")
case let .a2(y):
print("let a2 \(y)")
}
}
For example:
var x = A.a1(x: 1)
var y = A.a2(y: "hello")
doSomething(a: x) // Prints a1 let 1
doSomething(a: y) // Prints let a2 hello
As you notice I can use the syntax case .a1(let x) and case let .a2(y) with no apparent difference.
So I wanted to understand: are there valid reasons to have both syntaxes, or they are purely for convenience? For example: are there a lower-level (compiler, memory) difference between those options? Are there any examples when one or the other wouldn't work as well? Thanks
As you notice I can use the syntax case .a1(let x) and case let .a2(y) with no apparent difference.
You're right, there's very little difference between these two syntaxes — the case let syntax is for convenience.
are there valid reasons to have both syntaxes, or they are purely for convenience? For example: are there a lower-level (compiler, memory) difference between those options?
Yes, but it best applies to enum cases with more than one associated value, as it allows you to avoid having to repeat let for every single associated value in the case:
enum A {
case a1(x: Int)
case a2(y: String)
case a3(x: Int, y: String)
case a4(x: Int, y: String, z: Double)
}
let a: A = ...
switch a {
// Inner `let`:
case .a1(let x):
print(x)
// Equivalent outer `let`:
case let .a2(y):
print(y)
// Inner `let`s can get repetitive:
case .a3(let x, let y):
print(x, y)
// More convenient outer `let`s:
case let .a4(x, y, z):
print(x, y, z)
}
An explanation from the Swift language guide:
If all of the associated values for an enumeration case are extracted as constants, or if all are extracted as variables, you can place a single var or let annotation before the case name, for brevity
This is a purely syntactic convenience, and makes absolutely no difference in compilation.
If you're curious about how this shakes out from the language grammar:
switch statements have a list of switch casesdefault cases) have a case label (which has one or more case items)case let .a4(...) variant, the pattern is bound as a value binding pattern whose internal pattern binds as an enum case patterncase .a3(let...) variant, the pattern is bound directly as an enum case pattern, whose tuple pattern contents each bind a value binding patternThe grammar technically allows for a lot of flexibility here, but the compiler ensures that you either have a var/let outside of the case label itself, or bind each variable inside of the case with a var/let internally
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With