Last active
June 2, 2019 12:56
-
-
Save janodev/b3da205452015678f5422940628b06ba to your computer and use it in GitHub Desktop.
Examples of pattern matching in Swift from http://alisoftware.github.io/swift/pattern-matching/2016/03/27/pattern-matching-1/
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// BASIC SWITCH | |
enum Media { case Book } | |
extension Media : CustomStringConvertible | |
{ | |
var description: String { | |
switch self { | |
case .Book: return "bible" | |
} | |
} | |
} | |
// SWITCH WITH ASSOCIATED VALUES | |
enum Media { | |
case Book(title: String, author: String) | |
} | |
extension Media { | |
var description: String { | |
switch self { | |
case .Book(title: let aTitle, author: _): return aTitle | |
default: return "" | |
} | |
} | |
} | |
// SWITCH MATCHING A LITERAL VALUE | |
import Foundation | |
enum Response { | |
case HTTPResponse(statusCode: Int) | |
case NetworkError(NSError) | |
} | |
let response: Response = .HTTPResponse(statusCode: 301) | |
switch response { | |
case .HTTPResponse(200): () | |
case .HTTPResponse(404): () | |
default: () | |
} | |
// SWITCH MATCHING MULTIPLE PATTERNS | |
enum Media { | |
case Book(title: String) | |
case Movie(title: String) | |
} | |
extension Media { | |
var description: String { | |
switch self { | |
case .Book(title: _), .Movie(title: _): return "stuff" | |
// multiple case with associated values can't declare variables | |
} | |
} | |
} | |
// SWITCH WITHOUT ARGUMENT LABELS | |
enum Media { | |
case Book(title: String) | |
case Movie(title: String) | |
} | |
extension Media { | |
var description: String { | |
switch self { | |
case let .Book(title): return title | |
case let .Movie(title): return title | |
} | |
} | |
} | |
// SWITCH TREATING THE ASSOCIATED VALUES AS A TUPLE | |
enum Media { | |
case Book(title: String, year: Int) | |
case Movie(title: String, year: Int) | |
} | |
extension Media { | |
var description: String { | |
switch self { | |
case let .Book(tuple): return tuple.title | |
case let .Movie(tuple): return tuple.title | |
// the pattern could also be nothing, or (_), or (_, _) | |
} | |
} | |
} | |
// SWITCH WITH WHERE | |
enum Media { | |
case Book(title: String, year: Int) | |
case Movie(title: String, year: Int) | |
} | |
extension Media { | |
var year: Int { | |
switch self { | |
case let .Book(_,year) where year > 1930: return year | |
case let .Movie(_,year) where year > 1930: return year | |
default: return 0 | |
} | |
} | |
} | |
// SWITCH MATCHING TUPLES | |
import Foundation | |
let point = CGPoint(x: 7, y: 0) | |
switch (point.x, point.y) { | |
case (0,0): print("On the origin!") | |
case (0,_): print("x=0: on Y-axis!") | |
case (_,0): print("y=0: on X-axis!") | |
case (let x, let y) where x == y: print("On y=x") | |
default: print("Quite a random point here.") | |
} | |
// SWITCH MATCHING CHARACTERS | |
let car: Character = "J" | |
switch car { | |
case "A", "E", "I", "O", "U", "Y": print("Vowel") | |
default: print("Consonant") | |
} | |
// SWITCH MATCHING RANGES | |
// ranges of Ints | |
let count = 7 | |
switch count { | |
case Int.min..<0: print("Negative count, really?") | |
case 0: print("Nothing") | |
case 1: print("One") | |
case 2..<5: print("A few") | |
case 5..<10: print("Some") | |
default: print("Many") | |
} | |
// ranges of characters | |
func charType(car: Character) -> String { | |
switch car { | |
case "A", "E", "I", "O", "U", "Y", "a", "e", "i", "o", "u", "y": | |
return "Vowel" | |
case "A"..."Z", "a"..."z": | |
return "Consonant" | |
default: | |
return "Other" | |
} | |
} | |
print("Jules Verne".characters.map(charType)) | |
// SWITCH ON DIFFERENT TYPES | |
protocol Foobar{} | |
extension String: Foobar {} | |
extension Int: Foobar {} | |
for thing in ["one", 2] as [Foobar] { | |
switch thing { | |
case let thing as String: print("string") | |
case let thing as Int: print("int") | |
default: () | |
} | |
} | |
// PATTERN MATCHING OPERATOR FOR A CUSTOM TYPE | |
struct Affine { | |
var a: Int | |
var b: Int | |
} | |
// custom pattern matching operator for the Affine custom type | |
// rhs will be the element in the switch, lhs will be the element in the case | |
func ~= (lhs: Affine, rhs: Int) -> Bool { | |
return rhs % lhs.a == lhs.b | |
} | |
switch 5 { | |
case Affine(a: 2, b: 0): print("Even number") | |
case Affine(a: 3, b: 1): print("3x+1") | |
case Affine(a: 3, b: 2): print("3x+2") // match because 5%3 == 2 | |
default: print("Other") | |
} | |
// SWITCH WITH OPTIONALS | |
let anOptional: Int? = 2 | |
switch anOptional { | |
// x? is syntactic sugar for .Some(x) | |
case 0?: print("Zero") | |
case 1?: print("One") | |
case 2?: print("Two") | |
case nil: print("None") | |
default: print("Other") | |
} | |
// SWITCH ON RAWVALUE | |
enum MenuItem: Int { | |
case Home | |
case Account | |
case Settings | |
} | |
switch 2 { | |
case MenuItem.Home.rawValue: () | |
case MenuItem.Account.rawValue: () | |
case MenuItem.Settings.rawValue: print(2) | |
default: () | |
} | |
// IF CASE LET WHERE | |
enum Media { | |
case Movie(title: String, director: String, year: Int) | |
} | |
let m = Media.Movie(title: "Captain America: Civil War", director: "Russo Brothers", year: 2016) | |
if case let Media.Movie(_, _, year) = m where year < 2025 { | |
print("Something seems wrong: the movie's year is before the first movie ever made.") | |
} | |
// GUARD CASE LET | |
enum NetworkResponse { | |
case Response(NSURLResponse, NSData) | |
case Error(NSError) | |
} | |
func processRequestResponse(response: NetworkResponse) | |
{ | |
guard case let .Response(urlResp, data) = response, | |
let httpResp = urlResp as? NSHTTPURLResponse | |
where 200..<300 ~= httpResp.statusCode else | |
{ | |
print("Invalid response, can't process") | |
return | |
} | |
print("Processing \(data.length) bytes…") | |
} | |
// FOR CASE LET | |
enum Media { | |
case Movie(title: String, director: String, year: Int) | |
} | |
let mediaList: [Media] = [ | |
.Movie(title: "Harry Potter and the Prisoner of Azkaban", director: "Alfonso Cuarón", year: 2004), | |
.Movie(title: "J.K. Rowling: A Year in the Life", director: "James Runcie", year: 2007), | |
] | |
print("Movies only:") | |
for case let Media.Movie(title, _, year) in mediaList { | |
print(" - \(title) (\(year))") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment