Swift 2 - Pattern Matching in "If"

Swift 2 - Pattern matching in if

All it really means is that if statements now support pattern matching like switch statements already have. For example, the following is now a valid way of using if/else if/else statements to "switch" over the cases of an enum.

enum TestEnum {
case One
case Two
case Three
}

let state = TestEnum.Three

if case .One = state {
print("1")
} else if case .Two = state {
print("2")
} else {
print("3")
}

And the following is now an acceptable way of checking if someInteger is within a given range.

let someInteger = 42
if case 0...100 = someInteger {
// ...
}

Here are a couple more examples using the optional pattern from The Swift Programming Language

let someOptional: Int? = 42
// Match using an enumeration case pattern
if case .Some(let x) = someOptional {
print(x)
}

// Match using an optional pattern
if case let x? = someOptional {
print(x)
}

Pattern matching in a Swift for loop

You can combine a pattern matching conditional cast with a where clause like so:

let myStuff: [AnyObject] = [5, "dog", 11, 15, "cat"]

// item will be an Int, and divisible by 5
for case let item as Int in myStuff where item % 5 == 0 {
print(item)
}

// Prints:
// 5
// 15

Custom pattern matching in Swift 2.2 not working as expected

switch testLine {
case _ where testLine.characters.count == 0:
print("Empty")
case _ where testLine.isOfType(.Event): print("Event")
case _ where testLine.isOfType(.Data): print("Data")
default: print("Unknown Type")
}

/* prints
Event
*/

still, try to rearrange it ...

it looks terrible, but this works, as expected

enum LineType : String {
case Event = "event:"
case Data = "data:"
}
func ~= (pattern: LineType, value: String) -> Bool {
return value.hasPrefix(pattern.rawValue)
}


let testLine = "event:yada-yada-yada"
let e = LineType.Event
let d = LineType.Data
switch testLine {
case let s where s.characters.count == 0: print("Empty")
case e: print("Event")
case d: print("Data")
default: print("Unknown Type")
}
/* prints
Event
*/

this should also work

...
case { return LineType.Event }(): print("Event")
...

or

...
case { LineType.Event }(): print("Event")
...

Use or logic with multiple if case statements

I would resort to some sort of isBar property on the enum itself, so that the "a or b" test remains readable:

enum MyEnum {
case foo, bar(_ prop: Int)

var isBar: Bool {
switch self {
case .bar: return true
default: return false
}
}
}

let var1 = MyEnum.foo
let var2 = MyEnum.bar(1)

let eitherIsBar = var1.isBar || var2.isBar

Swift switch matching multiple conditionals

A switch statement compares a value against patterns and executes
the code based on the first successful match.

If your intention is to match against multiple patterns and execute
code for all matches then use multiple if statements.
The same case patterns can be used:

if case (0, 0) = somePoint {
print("\(somePoint) is at the origin")
}
if case (_, 0) = somePoint {
print("\(somePoint) is on the x-axis")
}
// ...
if case (-2...2, -2...2) = somePoint {
print("\(somePoint) is inside the box")
}
// ...

Can I use the range operator with if statement in Swift?

You can use the "pattern-match" operator ~=:

if 200 ... 299 ~= statusCode {
print("success")
}

Or a switch-statement with an expression pattern (which uses the pattern-match
operator internally):

switch statusCode {
case 200 ... 299:
print("success")
default:
print("failure")
}

Note that ..< denotes a range that omits the upper value, so you probably want
200 ... 299 or 200 ..< 300.

Additional information: When the above code is compiled in Xcode 6.3 with
optimizations switch on, then for the test

if 200 ... 299 ~= statusCode

actually no function call is generated at all, only three assembly instruction:

addq    $-200, %rdi
cmpq $99, %rdi
ja LBB0_1

this is exactly the same assembly code that is generated for

if statusCode >= 200 && statusCode <= 299

You can verify that with


xcrun -sdk macosx swiftc -O -emit-assembly main.swift

As of Swift 2, this can be written as

if case 200 ... 299 = statusCode {
print("success")
}

using the newly introduced pattern-matching for if-statements.
See also Swift 2 - Pattern matching in "if".

String pattern matching in Swift switch statements

I found the issue. I did not isolate the problem correctly.
The issue was that my source data had a slightly different "-" character which Swift (rightly so) did not consider equal to the condition in the switch cases. I sanitized the inputs and now it works correctly. In the playground I did manually write the input so the issue did not arise.

Thank you so much anyway!



Related Topics



Leave a reply



Submit