Compound switch cases: may we have a single common value binding for compound enum cases that have the same type of associated value?
No, this is not possible; in the value binding examples above, x
must be bound in every pattern, and this must hold separately for every pattern in the compound cases.
Quoting the Language Guide - Control Flow [emphasis mine]
Compound cases can also include value bindings. All of the patterns of
a compound case have to include the same set of value bindings, and
each binding has to get a value of the same type from all of the
patterns in the compound case. This ensures that, no matter which part
of the compound case matched, the code in the body of the case can
always access a value for the bindings and that the value always has
the same type.
I we try to omit the binding in one of the patterns in the compound example above, we are given quite an self-explanatory error message on the subject:
func foo(_ foo: Foo) -> Int {
switch foo {
case .bar(_), .baz(let x), .bax(let x): return x
case .fox: return 0
}
}
error: 'x' must be bound in every pattern
This holds even if we don't use x
in the body that follows
func foo(_ foo: Foo) -> Int {
switch foo {
case .bar(_), .baz(let x), .bax(let x): return 0
case .fox: return 0
}
} // same error
Is it possible to write compound switch case between enum associated value conditional and another enum case?
You don't need a where-clause to match .cloudy(coverage: 0)
, just
case .cloudy(coverage: 0), .sunny:
print("☀️")
Another option is to use fallthrough
, for example
case .cloudy(let coverage) where coverage < 10:
fallthrough
case .sunny:
print("☀️")
Unwrapping associated value for all cases in switch
Try this in Playground.
enum RowType {
case single(_ content: [Any])
case double(_ content: [Any])
case triple(_ content: [Any])
case noVal
var associatedValue: Any? {
get {
let mirror = Mirror(reflecting: self)
if let associated = mirror.children.first {
return associated.value
}
print("WARNING: Enum option of \(self) does not have an associated value")
return nil
}
}
}
let row : RowType = .double([1,2,3])
let rowNoVal : RowType = .noVal
row.associatedValue
rowNoVal.associatedValue
Binding to an associated value of an enum
You can extend your enumeration and add a text property with a getter and a setter:
extension Choice {
var text: String {
get {
switch self {
case let .one(string): return string
case let .two(string): return string
}
}
set {
switch self {
case .one: self = .one(newValue)
case .two: self = .two(newValue)
}
}
}
}
Then you can simply pass the text property:
TextField("", text: $choice.text)
Single-element parethesized expressions/tuples vs common use of parentheses
From Types in the Swift book:
If there is only one element inside the parentheses, the type is
simply the type of that element. For example, the type of(Int)
is
Int
, not(Int)
.
So the type of (2)
or (2+4)
is simply Int
, and the *
in (2+4)*5
is
just integer multiplication.
Swift - Multiple Switch Cases
how about :
struct Object{
var type = 1
}
let lowType = min(object1.type,object2.type)
let highType = max(object1.type,object2.type)
switch( lowType, highType )
{
case (1,1):
doSome()
case (1,2):
doSome2()
case (1,3):
doSome3()
...
// you will only need to specify the combinations where the first
// type is less or equal to the other.
}
If you will be doing this often, you could define a minMax function to further reduce the amount of code needed each time:
func minMax<T:Comparable>(_ a:T, _ b:T) ->(T,T)
{ return a<b ? (a,b) : (b,a) }
switch minMax(object1.type,object2.type)
{
case (1,1):
doSome()
case (1,2):
doSome2()
...
note that you can also put each inverted pair in its case statement:
switch(object1.type,object2.type)
{
case (1,1):
doSome()
case (1,2),(2,1):
doSome2()
case (1,3),(3,1):
doSome3()
...
}
[UPDATE]
If you have more than two values to compare in a "permutation insensitive" fashion, you could expand on the minMax() idea by creating variants with more values:
func minToMax<T:Comparable>(_ a:T, _ b:T) -> (T,T)
{ return a<b ? (a,b) : (b,a) }
func minToMax<T:Comparable>(_ a:T, _ b:T, _ c:T) -> (T,T,T)
{ return { ($0[0],$0[1],$0[2]) }([a,b,c].sorted()) }
func minToMax<T:Comparable>(_ a:T, _ b:T, _ c:T, _ d:T) -> (T,T,T,T)
{ return { ($0[0],$0[1],$0[2],$0[3]) }([a,b,c,d].sorted()) }
switch minToMax(object1.type,object2.type,object3.type)
{
case (1,2,3) : doSome1() // permutations of 1,2,3
case (1,2,4) : doSome2() // permutations of 1,2,4
case (1,2,_) : doSome3() // permutations of 1,2,anything else
case (1,5...6,10) : doSome4() // more elaborate permutations
...
}
}
Using Switch Statements in Swift - Value binding INSIDE the parentheses vs outside?
Case 1 is more concise, and better suited for the general case.
Case 2 is more granular. Consider this case:
switch myNumbers {
case (let x, var y):
// x is a constant, y is mutable.
print("the value of x is \(x)")
default:
print("n/a")
}
.net core switch expression incrementing with wrong value
Remember that the compound assignment operator a += b
is the same as a = a + b
(except that a
is evaluated only once), see §7.17.2 of the spec.
Here's a slightly simpler example which doesn't use a switch, and has the same effect:
int j = 2;
int A()
{
j = 10;
return 0;
}
j = j + A();
If you don't want to think in terms of local functions, you can also write this as a class:
class C
{
private int j;
public void Test()
{
j = 2;
j = j + A();
}
private int A()
{
j = 10;
return 0;
}
}
The compiler will:
- Start by evaluating
j + A()
:- Push the current value of
j
, which is2
, onto the stack - Call
A()
, which setsj
to10
and returns0
- Push the return value of
A()
, which is0
, onto the stack - Add together the two values on the stack:
2 + 0
- Push the current value of
- Assign this value to
j
If you write the assignment the other way around, as j = A() + j
, then its final value is 10
. If you follow the same sequence of steps as above, you'll see why.
This general approach -- changing a variable as a side-effect of an expression which also changes that variable -- is a bad idea. It leads to very hard-to-understand code.
Switch statement in Swift
The usual rules for the FizzBuzz game
are to replace every multiple of 3 by "Fizz", every multiple of 5 by "Buzz", and
every multiple of both 3 and 5 by "FizzBuzz".
This can be done with a switch statement on the tuple (i % 3, i % 5)
.
Note that _
means "any value":
for i in 1 ... 100 {
switch (i % 3, i % 5) {
case (0, 0):
print("FizzBuzz")
case (0, _):
print("Fizz")
case (_, 0):
print("Buzz")
default:
print(i)
}
}
Related Topics
Search Multiple Words in One String in Swift
How to Know Where Optional Chaining Is Breaking
Build Realm for Swift 3 & Xcode 8
Swift Firebase Custom Object with Document Id
Using @Fetchrequest(Entity: ) for Swiftui MACos App Crashes
How to Set Realtime Thread in Swift
Urlsessiondelegate's Didwritedata Not Call When App Is Going to Background in iOS12
Swift 3 Init Method That Accepts JSON with Optional Parameters
How to Compile "Hello World" Program with Swift on Ubuntu 14.04
Swift and Objectmapper: Nsdate with Min Value
Best Way to Handle Errors from Async Closures in Swift 2
How to Star a Repo with Github API
Closures Return Value (Previously Completionblock)
Nsposixerrordomain When Binding to Socket on MACos 10.12
Unknown Error When Adding an CSSearchableitem to Core Spotlight (Macos)