7.2 Loops

Loops allow you to execute a block of code repeatedly. Rust provides several looping constructs, some of which differ significantly from those in C.

7.2.1 The loop Construct

The loop construct creates an infinite loop unless explicitly broken out of.

fn main() {
    let mut count = 0;
    loop {
        println!("Count is: {}", count);
        count += 1;
        if count == 5 {
            break;
        }
    }
}

Key Points:

  • Infinite Loop: Continues indefinitely unless break is used.
  • Can Return Values: Loops can return values using break with a value.

Loops as Expressions

Loops can return values when you use break with a value.

fn main() {
    let mut count = 0;
    let result = loop {
        count += 1;
        if count == 10 {
            break count * 2;
        }
    };
    println!("The result is: {}", result);
}

Explanation: When count reaches 10, the loop breaks and returns count * 2, which is 20. The value is assigned to result.

7.2.2 The while Loop

A while loop runs as long as a condition is true.

fn main() {
    let mut count = 0;
    while count < 5 {
        println!("Count is: {}", count);
        count += 1;
    }
}

Key Points:

  • Condition Checked Before Each Iteration: If the condition is false initially, the loop body may not execute at all.
  • Mutable Variables: Often used with variables that need to be updated within the loop.

Comparison with C

C Code:

int count = 0;
while (count < 5) {
    printf("Count is: %d\n", count);
    count++;
}

7.2.3 The for Loop

Rust's for loop is used to iterate over collections or ranges. It differs from the traditional C-style for loop.

Iterating Over Ranges

fn main() {
    for i in 0..5 {
        println!("i is {}", i);
    }
}

Key Points:

  • Range Syntax start..end: Includes start, excludes end.
  • Inclusive Range ..=: Use start..=end to include end.

Iterating Over Collections

fn main() {
    let numbers = [10, 20, 30];
    for number in numbers {
        println!("Number is {}", number);
    }
}

Explanation: You can iterate directly over arrays and slices without needing to call .iter().

Comparison with C's for Loop

C Code:

for (int i = 0; i < 5; i++) {
    printf("i is %d\n", i);
}

Note: Rust does not have a traditional C-style for loop with initialization, condition, and increment expressions. Rust's for loop is more like a "for-each" loop, emphasizing safety and clarity.

7.2.4 Labeled Breaks and Continues in Nested Loops

In Rust, the loop, while, and for constructs can all use the break and continue keywords. The continue keyword skips the rest of the current loop iteration and jumps to the beginning of the loop. In the case of nested loops, labels can be used to specify which loop you want to break out of or continue.

fn main() {
    'outer: for i in 0..3 {
        for j in 0..3 {
            if i == j {
                continue 'outer;
            }
            if i + j == 4 {
                break 'outer;
            }
            println!("i = {}, j = {}", i, j);
        }
    }
}

Key Points:

  • Labels: Defined using a single quote followed by a name (e.g., 'outer).
  • break and continue with Labels: Control flow can break out of or continue specific loops.

Comparison with C

C does not have labeled break or continue. Similar behavior can be achieved using goto, but this is generally discouraged due to readability and maintainability concerns.