Advanced Operators and Custom Operators

27.1 Bitwise and Overflow Operators

let initial: UInt8 = 0b0000_1111
~initial                  // 0b1111_0000
initial & 0b0011_1100     // AND
initial | 0b1111_0000     // OR
initial ^ 0b1111_1111     // XOR
initial << 2, initial >> 1
let pink: UInt32 = 0xCC6699
let red = (pink & 0xFF0000) >> 16       // 0xCC

var max = UInt8.max
max = max &+ 1            // 0 (wraps instead of trapping)
let (result, overflow) = Int.max.addingReportingOverflow(1)
Int.max.multipliedFullWidth(by: 2)

27.2 Operator Overloading

struct Vector2D: Equatable {
    var x = 0.0, y = 0.0

    static func + (lhs: Vector2D, rhs: Vector2D) -> Vector2D { Vector2D(x: lhs.x + rhs.x, y: lhs.y + rhs.y) }
    static prefix func - (v: Vector2D) -> Vector2D { Vector2D(x: -v.x, y: -v.y) }
    static func += (lhs: inout Vector2D, rhs: Vector2D) { lhs = lhs + rhs }
    static func * (v: Vector2D, k: Double) -> Vector2D { Vector2D(x: v.x * k, y: v.y * k) }
}
var v = Vector2D(x: 1, y: 2) + Vector2D(x: 3, y: 4)
v += Vector2D(x: 1, y: 1)
let inverted = -v

27.3 Custom Operators and Precedence

Use custom operators sparingly. They hurt readability unless they're domain-standard (math, parsers, DSLs).

prefix operator +++
infix operator **: ExponentiationPrecedence
precedencegroup ExponentiationPrecedence {
    higherThan: MultiplicationPrecedence
    associativity: right
}
infix operator |>: ForwardPipePrecedence
precedencegroup ForwardPipePrecedence { associativity: left; lowerThan: TernaryPrecedence }

extension Vector2D {
    static prefix func +++ (v: inout Vector2D) -> Vector2D { v += v; return v }
}
func ** (base: Double, exp: Double) -> Double { pow(base, exp) }
func |> <A, B>(value: A, f: (A) -> B) -> B { f(value) }

2 ** 3 ** 2                       // 512 (right-associative)
"swift" |> { $0.uppercased() } |> { $0 + "!" }