Generics

21.1 Generic Functions

func swapTwo<T>(_ a: inout T, _ b: inout T) { (a, b) = (b, a) }

func largest<T: Comparable>(_ items: [T]) -> T? {
    guard var best = items.first else { return nil }
    for item in items where item > best { best = item }
    return best
}
largest([3, 9, 2]); largest(["b", "a"])

21.2 Generic Types

struct Queue<Element> {
    private var inbox: [Element] = []
    private var outbox: [Element] = []
    mutating func enqueue(_ e: Element) { inbox.append(e) }
    mutating func dequeue() -> Element? {
        if outbox.isEmpty { outbox = inbox.reversed(); inbox.removeAll() }
        return outbox.popLast()
    }
    var isEmpty: Bool { inbox.isEmpty && outbox.isEmpty }
}

enum Either<Left, Right> {
    case left(Left)
    case right(Right)
}

struct Pair<A, B> { let first: A; let second: B }
extension Pair: Equatable where A: Equatable, B: Equatable {}

21.3 Constraints and where Clauses

func allEqual<C: Collection>(_ c: C) -> Bool where C.Element: Equatable {
    guard let first = c.first else { return true }
    return c.allSatisfy { $0 == first }
}

func merge<C1: Sequence, C2: Sequence>(_ a: C1, _ b: C2) -> [C1.Element]
    where C1.Element == C2.Element, C1.Element: Comparable {
    (Array(a) + Array(b)).sorted()
}

extension Collection where Element: Numeric {
    func sum() -> Element { reduce(0, +) }
}

extension Array where Element == String {
    func joinedWithCommas() -> String { joined(separator: ", ") }
}

protocol Cache {
    associatedtype Key: Hashable
    associatedtype Value
    subscript(key: Key) -> Value? { get set }
}

21.4 Generic Specialization and Performance

Swift generics are compiled with specialization where the concrete types are visible (no boxing overhead). Use @inlinable to allow cross-module specialization in libraries.

Unspecialized generic code uses witness tables (dynamic dispatch through protocols).