Enumerations

11.1 Basic Enums

enum Direction {
    case north, south, east, west
}
var heading = Direction.north
heading = .east                      // type inferred

switch heading {
case .north: print("Up")
case .south: print("Down")
case .east, .west: print("Sideways")
}

11.2 Raw Values

enum Planet: Int {
    case mercury = 1, venus, earth, mars    // implicit raw values 1, 2, 3, 4
}
Planet.earth.rawValue          // 3
Planet(rawValue: 4)            // Optional(.mars)

enum HTTPMethod: String {
    case get = "GET", post = "POST"
    case delete                // raw value "delete"
}

11.3 Associated Values

enum Barcode {
    case upc(Int, Int, Int, Int)
    case qrCode(String)
}

enum NetworkResult {
    case success(data: Data, statusCode: Int)
    case failure(Error)
    case loading(progress: Double)
}

func handle(_ result: NetworkResult) {
    switch result {
    case .success(let data, let code) where code == 200:
        print("OK \(data.count) bytes")
    case .success(_, let code):
        print("Status \(code)")
    case .failure(let error):
        print("Error: \(error)")
    case .loading(let progress):
        print("\(Int(progress * 100))%")
    }
}

if case .qrCode(let text) = Barcode.qrCode("hello") { print(text) }

11.4 Methods, Computed Properties and CaseIterable

enum Suit: String, CaseIterable {
    case hearts = "♥", diamonds = "♦", clubs = "♣", spades = "♠"

    var color: String {
        switch self {
        case .hearts, .diamonds: "red"
        case .clubs, .spades: "black"
        }
    }

    mutating func next() {
        let all = Self.allCases
        self = all[(all.firstIndex(of: self)! + 1) % all.count]
    }

    static var random: Suit { allCases.randomElement()! }
}
Suit.allCases.count        // 4

11.5 Recursive Enums

indirect enum Expr {
    case number(Int)
    case add(Expr, Expr)
    case multiply(Expr, Expr)

    func evaluate() -> Int {
        switch self {
        case .number(let n): n
        case .add(let l, let r): l.evaluate() + r.evaluate()
        case .multiply(let l, let r): l.evaluate() * r.evaluate()
        }
    }
}
let expr = Expr.add(.number(2), .multiply(.number(3), .number(4)))
expr.evaluate()   // 14