Swift Advanced Operators

Powerful operators for complex operations

⚡ What are Advanced Operators?

Advanced operators in Swift provide powerful ways to manipulate data including bitwise operations, overflow operators, and custom operators. They enable low-level programming and mathematical computations.


// Bitwise AND operator
let result = 0b1010 & 0b1100  // Binary: 1000 (8 in decimal)
print("Bitwise AND: \(result)")

// Nil-coalescing operator
let name: String? = nil
let displayName = name ?? "Guest"
print("Welcome, \(displayName)!")
                                    

Output:

Bitwise AND: 8

Welcome, Guest!

Advanced Operator Types

🔢

Bitwise Operators

Work with individual bits of data

let a = 0b1010  // 10
let b = 0b1100  // 12
let result = a & b  // 8
🔄

Overflow Operators

Handle integer overflow safely

let max = UInt8.max  // 255
let overflow = max &+ 1  // 0

Nil-Coalescing

Provide default values for optionals

let optional: String? = nil
let value = optional ?? "Default"
🎯

Range Operators

Create ranges of values

let range = 1...5  // 1,2,3,4,5
let halfOpen = 1..<5  // 1,2,3,4

🔹 Bitwise Operators

Bitwise operators work on the binary representation of numbers:

// Bitwise NOT (~) - flips all bits
let initialBits: UInt8 = 0b00001111  // 15
let invertedBits = ~initialBits       // 11110000 (240)
print("NOT \(initialBits): \(invertedBits)")

// Bitwise AND (&) - 1 only if both bits are 1
let firstSixBits: UInt8  = 0b11111100  // 252
let lastSixBits: UInt8   = 0b00111111  // 63
let middleFourBits = firstSixBits & lastSixBits  // 00111100 (60)
print("AND result: \(middleFourBits)")

// Bitwise OR (|) - 1 if either bit is 1
let someBits: UInt8 = 0b10110010  // 178
let moreBits: UInt8 = 0b01011110  // 94
let combinedbits = someBits | moreBits  // 11111110 (254)
print("OR result: \(combinedbits)")

// Bitwise XOR (^) - 1 if bits are different
let firstBits: UInt8 = 0b00010100  // 20
let otherBits: UInt8 = 0b00000101  // 5
let outputBits = firstBits ^ otherBits  // 00010001 (17)
print("XOR result: \(outputBits)")

Output:

NOT 15: 240

AND result: 60

OR result: 254

XOR result: 17

🔹 Bit Shifting Operators

Shift bits left or right to multiply or divide by powers of 2:

// Left shift (<<) - multiply by 2^n
let shiftBits: UInt8 = 4  // 00000100
let leftShift = shiftBits << 1  // 00001000 (8)
let leftShift2 = shiftBits << 2  // 00010000 (16)
print("4 << 1 = \(leftShift)")
print("4 << 2 = \(leftShift2)")

// Right shift (>>) - divide by 2^n
let rightShift = shiftBits >> 1  // 00000010 (2)
let rightShift2 = shiftBits >> 2  // 00000001 (1)
print("4 >> 1 = \(rightShift)")
print("4 >> 2 = \(rightShift2)")

// Practical example: Fast multiplication/division
func fastMultiplyBy8(_ number: Int) -> Int {
    return number << 3  // Shift left by 3 positions (2^3 = 8)
}

func fastDivideBy4(_ number: Int) -> Int {
    return number >> 2  // Shift right by 2 positions (2^2 = 4)
}

print("Fast multiply 5 by 8: \(fastMultiplyBy8(5))")
print("Fast divide 20 by 4: \(fastDivideBy4(20))")

Output:

4 << 1 = 8

4 << 2 = 16

4 >> 1 = 2

4 >> 2 = 1

Fast multiply 5 by 8: 40

Fast divide 20 by 4: 5

🔹 Overflow Operators

Handle integer overflow without crashing:

// Regular operators crash on overflow
// let overflow = UInt8.max + 1  // This would crash!

// Overflow addition (&+)
let maxValue = UInt8.max  // 255
let overflowAdd = maxValue &+ 1  // Wraps to 0
print("255 &+ 1 = \(overflowAdd)")

// Overflow subtraction (&-)
let minValue = UInt8.min  // 0
let overflowSub = minValue &- 1  // Wraps to 255
print("0 &- 1 = \(overflowSub)")

// Overflow multiplication (&*)
let largeNumber: UInt8 = 200
let overflowMul = largeNumber &* 2  // Wraps around
print("200 &* 2 = \(overflowMul)")

// Practical example: Circular buffer index
func nextIndex(current: UInt8, bufferSize: UInt8) -> UInt8 {
    return (current &+ 1) % bufferSize
}

let currentIndex: UInt8 = 7
let bufferSize: UInt8 = 8
let next = nextIndex(current: currentIndex, bufferSize: bufferSize)
print("Next index after \(currentIndex): \(next)")

Output:

255 &+ 1 = 0

0 &- 1 = 255

200 &* 2 = 144

Next index after 7: 0

🔹 Nil-Coalescing Operator

The nil-coalescing operator (??) provides default values for optionals:

// Basic nil-coalescing
let optionalName: String? = nil
let userName = optionalName ?? "Anonymous"
print("User: \(userName)")

// With non-nil value
let optionalAge: Int? = 25
let userAge = optionalAge ?? 0
print("Age: \(userAge)")

// Chaining nil-coalescing
let firstName: String? = nil
let lastName: String? = nil
let nickname: String? = "Swift Learner"
let displayName = firstName ?? lastName ?? nickname ?? "Unknown"
print("Display name: \(displayName)")

// Function with optional return
func getUserPreference() -> String? {
    // Simulate getting user preference
    return nil
}

let theme = getUserPreference() ?? "light"
print("Theme: \(theme)")

// Practical example: Configuration with defaults
struct AppConfig {
    let serverURL: String
    let timeout: Int
    let enableLogging: Bool
    
    init(serverURL: String? = nil, timeout: Int? = nil, enableLogging: Bool? = nil) {
        self.serverURL = serverURL ?? "https://api.example.com"
        self.timeout = timeout ?? 30
        self.enableLogging = enableLogging ?? false
    }
}

let config = AppConfig(timeout: 60)
print("Server: \(config.serverURL), Timeout: \(config.timeout)s")

Output:

User: Anonymous

Age: 25

Display name: Swift Learner

Theme: light

Server: https://api.example.com, Timeout: 60s

🔹 Range Operators

Create ranges for loops, arrays, and collections:

// Closed range operator (...)
let closedRange = 1...5
print("Closed range includes:")
for number in closedRange {
    print(number, terminator: " ")
}
print()

// Half-open range operator (..<)
let halfOpenRange = 1..<5
print("Half-open range includes:")
for number in halfOpenRange {
    print(number, terminator: " ")
}
print()

// One-sided ranges
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

// From index to end
let fromThree = numbers[3...]
print("From index 3: \(Array(fromThree))")

// From start to index
let upToFive = numbers[...5]
print("Up to index 5: \(Array(upToFive))")

// From start up to (but not including) index
let upToFour = numbers[..<4]
print("Up to index 4: \(Array(upToFour))")

// Practical example: String slicing
let text = "Hello, Swift!"
let startIndex = text.index(text.startIndex, offsetBy: 7)
let endIndex = text.index(text.startIndex, offsetBy: 12)
let substring = text[startIndex..<endIndex]
print("Substring: \(substring)")

Output:

Closed range includes:

1 2 3 4 5

Half-open range includes:

1 2 3 4

From index 3: [4, 5, 6, 7, 8, 9, 10]

Up to index 5: [1, 2, 3, 4, 5, 6]

Up to index 4: [1, 2, 3, 4]

Substring: Swift

🧠 Test Your Knowledge

What does the nil-coalescing operator (??) do?