Start learning free

LESSON 85 OF 414 · CONDITIONAL STATEMENTS

Combining Logical Operators in Rust: &&, || and Parentheses

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

    RUST · CONDITIONAL STATEMENTS

    Combining Logical Operators in Rust, explained

    Why you combine operators

    Real conditions often mix "and" with "or". A visitor may be let in if they are a special student, or if their age falls in a range, and the range itself needs two comparisons. Rust lets you build such conditions from &&, || and !, with parentheses to say which parts belong together.

    Parentheses change the meaning

    Take the expression 7 >= 10 && (5 == 7 || 9 < 12). The parentheses group the two comparisons joined by ||, so it reads as condition1 && condition2:

    • condition1 is 7 >= 10, which is false.
    • condition2 is (5 == 7 || 9 < 12), which is true, because 9 < 12 is true.

    A false and a true joined by && give false. Now move the parentheses: (7 >= 10 && 5 == 7) || 9 < 12. This reads as condition1 || condition2, where condition1 is (7 >= 10 && 5 == 7), which is false, and condition2 is 9 < 12, which is true. One true side is enough for ||, so the result is true. The same four comparisons give opposite answers depending on the grouping.

    Precedence: what happens without parentheses

    When you leave the parentheses out, Rust applies a fixed order. Comparisons are evaluated first, then &&, then ||. So && binds tighter than ||, just as multiplication binds tighter than addition. This means 7 >= 10 && 5 == 7 || 9 < 12 is read as (7 >= 10 && 5 == 7) || 9 < 12 and is true. Likewise true || false && false is true, while (true || false) && false is false.

    The rule is easy to forget, and a reader should not have to remember it. Add parentheses whenever && and || appear in the same condition, even where they change nothing. The compiler ignores redundant parentheses on boolean sub-expressions, so they cost nothing.

    Common mistakes

    • Assuming left to right. a || b && c is not (a || b) && c. The && part is grouped first.
    • Dropping a variable name. A range check needs the variable twice: age >= 18 && age <= 30. Shortened forms such as age >= 18 && <= 30 do not compile.
    • Mixing up the operator. A range check joined with || (age >= 18 || age <= 30) is true for every age.
    • Extra parentheses on the whole condition. Rust allows if (a) { ... } but warns that the parentheses are unnecessary. Group only the inner parts.

    The lesson's exercise

    The program decides whether a visitor may enter. A special student may always enter, and anyone else must be between 18 and 30.

    1. Declare specialStudent as a bool set to false and age as an i32 set to 23. Rust could infer both types, but the annotations make them explicit.
    2. Open an if that is true when specialStudent is true, or when the age is at least 18 and at most 30. Put the two age checks in parentheses: && already binds tighter than ||, but the parentheses show the grouping.
    3. Print "Let him in!" inside the if.
    4. Add an else that prints "Not allowed", so both outcomes produce output.
    let specialStudent: bool = false;
    let age: i32 = 23;
    if specialStudent || (age >= 18 && age <= 30) {
        println!("Let him in!");
    } else {
        println!("Not allowed");
    }
    

    Here specialStudent is false, so the left side of || does not decide anything. The group on the right is true, because 23 is at least 18 and at most 30, so the program prints Let him in!. With age set to 40, both sides would be false, and the output would be Not allowed. With specialStudent set to true, the age would not matter: || short-circuits and skips the right side.

    The compiler warns that specialStudent should have a snake case name, special_student. The warning does not stop the program.

    Key takeaways

    • Parentheses decide how conditions are grouped, and the grouping can change the result.
    • Without parentheses, comparisons come first, then &&, then ||.
    • Use parentheses whenever && and || appear together, so the reader does not have to recall the precedence rules.
    • A range check is two comparisons joined by &&, each naming the variable.
    Keep going with RustAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free