Swift
Programming
Conditional Statements
if let
Logical Operators

Using if let with logical or operator

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Swift's if let (optional binding) cannot be directly combined with || (logical OR) in a single condition. You cannot write if let a = optA || let b = optB because if let requires each binding to succeed for its variable to be available in the body. To achieve OR logic with optionals, use ?? (nil coalescing) to try multiple sources, chain if let with else if let, or use switch with pattern matching. This article covers all approaches with practical examples.

The Problem

swift
1let primaryName: String? = nil
2let fallbackName: String? = "Alice"
3
4// This does NOT compile — cannot use || with if let
5// if let name = primaryName || let name = fallbackName {
6//     print(name)
7// }

Swift requires each if let binding to succeed for the bound variable to exist in scope. With ||, only one branch needs to succeed, creating ambiguity about which variable is bound.

Solution 1: Nil Coalescing Operator (??)

swift
1let primaryName: String? = nil
2let fallbackName: String? = "Alice"
3
4// Try primary, then fallback
5if let name = primaryName ?? fallbackName {
6    print("Name: \(name)")  // "Name: Alice"
7}
8
9// Chain multiple fallbacks
10let name1: String? = nil
11let name2: String? = nil
12let name3: String? = "Charlie"
13
14if let name = name1 ?? name2 ?? name3 {
15    print("Found: \(name)")  // "Found: Charlie"
16}

?? returns the first non-nil value from left to right. Wrapping it in if let handles the case where all values are nil. This is the cleanest pattern when you want the first available value.

Solution 2: else if let Chain

swift
1let email: String? = nil
2let phone: String? = "555-1234"
3let address: String? = "123 Main St"
4
5if let contact = email {
6    print("Email: \(contact)")
7} else if let contact = phone {
8    print("Phone: \(contact)")
9} else if let contact = address {
10    print("Address: \(contact)")
11} else {
12    print("No contact info")
13}
14// Output: "Phone: 555-1234"

This pattern is useful when you need to know which optional succeeded, or when each branch has different handling logic.

Solution 3: switch with Optional Pattern Matching

swift
1let userInput: Int? = nil
2let defaultValue: Int? = 42
3
4switch (userInput, defaultValue) {
5case let (.some(value), _):
6    print("User input: \(value)")
7case let (_, .some(value)):
8    print("Default: \(value)")
9case (.none, .none):
10    print("No value available")
11}
12// Output: "Default: 42"

switch with tuple pattern matching gives full control over all combinations of nil and non-nil values.

Combining if let with Boolean Conditions

swift
1let age: Int? = 25
2let isVerified = true
3
4// if let WITH && (AND) — this works
5if let unwrappedAge = age, isVerified {
6    print("Verified user, age \(unwrappedAge)")
7}
8
9// if let with && and another if let — also works
10let name: String? = "Alice"
11let email: String? = "[email protected]"
12
13if let n = name, let e = email {
14    print("\(n)\(e)")
15}
16
17// Combining unwrap + condition
18if let n = name, n.count > 3 {
19    print("Name is long enough: \(n)")
20}

Swift allows combining if let with , (comma) for AND logic. Each condition must succeed for the body to execute. This is the built-in way to chain conditions with optional bindings.

Solution 4: Helper Function

swift
1func firstNonNil<T>(_ values: T?...) -> T? {
2    for value in values {
3        if let v = value {
4            return v
5        }
6    }
7    return nil
8}
9
10let a: String? = nil
11let b: String? = nil
12let c: String? = "Found it"
13
14if let result = firstNonNil(a, b, c) {
15    print(result)  // "Found it"
16}

A variadic helper function generalizes the nil-coalescing pattern for any number of optionals.

Solution 5: guard let with Fallback

swift
1func processUser(primary: User?, fallback: User?) {
2    guard let user = primary ?? fallback else {
3        print("No user available")
4        return
5    }
6
7    // user is guaranteed non-nil here
8    print("Processing \(user.name)")
9}

guard let with ?? is the preferred pattern inside functions — it exits early on failure and keeps the happy path unindented.

Real-World Example: Configuration Loading

swift
1struct Config {
2    let apiKey: String
3
4    init?() {
5        let envKey = ProcessInfo.processInfo.environment["API_KEY"]
6        let fileKey = try? String(contentsOfFile: ".env").trimmingCharacters(in: .whitespacesAndNewlines)
7        let defaultKey: String? = "dev-key-12345"
8
9        guard let key = envKey ?? fileKey ?? defaultKey else {
10            return nil
11        }
12        self.apiKey = key
13    }
14}

This shows the ?? chaining pattern in practice: try environment variable, fall back to file, then to a default value.

Common Pitfalls

  • Trying to use || with if let: if let a = x || let b = y does not compile in Swift. Use ??, else if let, or switch instead.
  • Confusing comma (AND) with || (OR): if let a = x, let b = y requires both optionals to be non-nil. This is AND logic, not OR.
  • Nil coalescing with different types: a ?? b requires both sides to be the same type. String? ?? Int? does not compile. Cast to a common type first.
  • Performance with expensive optional expressions: a ?? expensiveFunction() evaluates expensiveFunction() only if a is nil (auto-closure). But firstNonNil(a, expensiveFunction()) evaluates it eagerly. Use ?? chaining when evaluation cost matters.
  • Forgetting the else case: When using if let or guard let with ??, always handle the case where all options are nil. An unhandled nil case leads to silent failures.

Summary

  • Swift does not support if let with || — use alternative patterns
  • ?? (nil coalescing) chains are the simplest way to try multiple optionals: if let x = a ?? b ?? c
  • else if let chains work when each case needs different handling
  • switch with tuple pattern matching covers all nil/non-nil combinations
  • Use guard let ... ?? ... for early-exit patterns in functions
  • Comma-separated if let conditions are AND logic, not OR

Course illustration
Course illustration

All Rights Reserved.