Start learning free

LESSON 81 OF 415 · CONDITIONAL STATEMENTS

Combining Logical Operators in Swift: &&, || and !

Lesson Read the full explanation

Sometimes we need to combine logical operators to evaluate more complex conditions. For example:

7 >= 10 && (5 == 7 || 9 < 12) // Evaluates to false

Notice that we used parentheses to group 5 == 7 and 9 < 12 together. The computer interprets this line of code as condition1 && condition2 where:

  • condition1 is 7 >= 10, which is false
  • condition2 is (5 == 7 || 9 < 12), which is true
At least one of condition1 and condition2 is false, so the entire condition is false.

It is very important to use parentheses to tell the computer how to group the conditions together. If we change the parentheses in the example above to:

(7 >= 10 && 5 == 7) || 9 < 12 // Evaluates to true

Now the computer interprets this line of code as condition1 || condition2 where:

  • condition1 is (7 >= 10 && 5 == 7), which is false
  • condition2 is 9 < 12, which is true
At least one of condition1 and condition2 is true, so the entire condition is true.

Assignment
Follow the Coding Tutorial and let's combine some logical operators.


Hint
Look at the examples above if you get stuck.


STEP 1 OF 2
    Ctrl + Enter to check

    SWIFT · CONDITIONAL STATEMENTS

    Combining Logical Operators in Swift, explained

    Why combine operators

    Real conditions are rarely a single comparison. A person may get in because of a special status, or because their age falls inside a range. A range already needs two comparisons joined by &&, and the special status adds a third part joined by ||. Swift lets you mix &&, || and ! freely in one expression, as long as you are clear about how the parts group.

    Precedence and grouping

    When an expression contains several operators, Swift decides the grouping with precedence rules. Comparisons bind tightest, then &&, then ||. So a || b && c means a || (b && c), not (a || b) && c. Both operators evaluate from left to right and skip the right side when the left side already decides the result.

    Parentheses override the default. These two expressions use the same pieces and give different answers:

    print(7 >= 10 && (5 == 7 || 9 < 12))   // false
    print((7 >= 10 && 5 == 7) || 9 < 12)   // true
    

    In the first line, the parentheses group 5 == 7 || 9 < 12, which is true. The && then joins it with 7 >= 10, which is false, and an and needs both sides, so the result is false. In the second line, the left group (7 >= 10 && 5 == 7) is false, the right side 9 < 12 is true, and an or needs only one, so the result is true.

    The default grouping can hide a bug. Take true || false && false. Because && goes first, this is true || (false && false), which is true. The version (true || false) && false is false. Even when the default grouping is what you want, parentheses make that intent visible to the next reader.

    The exercise, step by step

    The lesson provides two constants:

    let specialStudent: Bool = false
    let age: Int = 23
    

    A person is let in when specialStudent is true, or when age is between 18 and 30, both ends included.

    1. Express the age range. "Between 18 and 30" is two comparisons that must both hold: age >= 18 and age <= 30. Both bounds are inclusive, so use >= and <=, and join them with &&. Swift has no chained form such as 18 <= age <= 30.
    2. Add the special-student case. Put specialStudent || in front of the range. A Bool can be used directly as a condition, so there is no need to write specialStudent == true.
    3. Group the range. Wrap the two age checks in parentheses. The grouping is the same without them, but the parentheses show that the range is one unit.
    4. Print in both cases. Print "Let him in!" in the if body, and add } else { with a print of "Not allowed" for everyone who fails both checks.
    let specialStudent: Bool = false
    let age: Int = 23
    
    if specialStudent || (age >= 18 && age <= 30) {
        print("Let him in!")
    } else {
        print("Not allowed")
    }
    

    With specialStudent set to false and age set to 23, the left side of || is false, so Swift checks the group. Since 23 is at least 18 and at most 30, the group is true and the program prints Let him in!.

    Trying other values

    Each of these inputs exercises a different path through the condition:

    • specialStudent = false, age = 17: the age check fails at age >= 18, so the program prints Not allowed.
    • specialStudent = false, age = 18 or 30: the boundaries count, so it prints Let him in!.
    • specialStudent = false, age = 31: it prints Not allowed.
    • specialStudent = true, age = 50: the left side is true, so the range is never evaluated, and it prints Let him in!.

    Common mistakes

    • Using || for the range. age >= 18 || age <= 30 is true for every integer, because every number is at least 18 or at most 30. A range needs &&.
    • Off-by-one bounds. Writing age > 18 would reject an 18-year-old, which contradicts "between 18 and 30" with inclusive ends.
    • Grouping the wrong parts. (specialStudent || age >= 18) && age <= 30 turns the special student into someone who still needs to be 30 or younger.
    • Comparing a Bool to true. specialStudent == true works, but specialStudent alone is shorter and reads better.

    Key takeaways

    • Precedence runs from comparisons to && to ||; parentheses override it.
    • Add parentheses whenever mixing && and ||, even if the default grouping would be right.
    • A range check is two comparisons joined with &&.
    • Swift stops evaluating as soon as the result is known.
    Keep going with SwiftAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free