Loops / Control Flow
Overview
In this lesson, we will explore the concept of loops in Rust, a fundamental aspect of control flow. Loops allow you to execute a block of code multiple times, which is crucial for tasks that require repetition, such as iterating over a collection or retrying an operation until a condition is met. Rust provides three primary loop constructs: loop
, while
, and for
. Each of these loops serves different purposes and offers unique control over the flow of your program.
1. Types of Loops in Rust
1.1 loop
- The Infinite Loop
The loop
keyword in Rust creates an unconditional loop that will run indefinitely unless explicitly stopped using the break
statement. This type of loop is useful when you want to repeat a block of code until a specific condition is met from within the loop.
Example: Basic Infinite Loop
fn main() { loop { println!("Hello, world!"); } }
Explanation:
- The
loop
will continuously print "Hello, world!" until manually interrupted (e.g., by pressingCtrl+C
in the terminal).
1.2 Breaking a Loop
To stop an infinite loop, you use the break
statement. This is often paired with a conditional check to exit the loop when a certain condition is met.
Example: Loop with Break
fn main() { let mut counter = 0; loop { counter += 1; if counter == 10 { break; } } println!("Counter reached: {}", counter); }
Explanation:
- The loop increments
counter
by 1 on each iteration. - When
counter
reaches 10, thebreak
statement exits the loop, and the final value ofcounter
is printed.
1.3 Returning Values from Loops
Rust allows you to return a value from a loop by placing the value after the break
statement. This can be useful when you need to perform an operation repeatedly until a desired result is achieved.
Example: Returning a Value from a Loop
fn main() { let mut counter = 0; let result = loop { counter += 1; if counter == 10 { break counter * 2; } }; println!("The result is: {}", result); }
Explanation:
- The loop runs until
counter
equals 10. - When the loop breaks, it returns
counter * 2
, which is 20 in this case, and assigns it toresult
.
2. Loop Labels
2.1 Nested Loops and Labels
When working with nested loops, it can become unclear which loop a break
or continue
statement is referring to. Rust provides loop labels to clarify this by explicitly naming loops and specifying which loop should be affected by break
or continue
.
Example: Using Loop Labels
fn main() { let mut count = 0; 'outer: loop { println!("Count = {}", count); let mut remaining = 10; loop { println!("Remaining = {}", remaining); if remaining == 9 { break; } if count == 2 { break 'outer; } remaining -= 1; } count += 1; } println!("End of loop with count = {}", count); }
Explanation:
- The
outer
loop is labeled with'outer:
. - The inner loop decreases
remaining
until it equals 9, then breaks out of the inner loop. - When
count
equals 2, the program breaks out of theouter
loop using the'outer
label.
3. while
Loops
3.1 Conditional Loops
The while
loop runs as long as a specified condition is true. This loop is useful for scenarios where the number of iterations is not known beforehand, and the loop needs to continue until a condition changes.
Example: While Loop
fn main() { let mut number = 3; while number != 0 { println!("{}!", number); number -= 1; } println!("Liftoff!"); }
Explanation:
- The
while
loop runs as long asnumber
is not equal to 0. - Each iteration prints the current value of
number
and then decrements it by 1. - When
number
reaches 0, the loop exits and "Liftoff!" is printed.
4. for
Loops
4.1 Iterating Over a Collection
The for
loop in Rust is used to iterate over collections such as arrays or ranges. It automatically handles iteration and avoids the common pitfalls associated with manually managing loop counters.
Example: Iterating Over an Array
fn main() { let a = [1, 2, 3, 4, 5]; for element in a { println!("The value is: {}", element); } }
Explanation:
- The
for
loop iterates over each element in the arraya
. - Each value is printed during its respective iteration.
4.2 Iterating Over a Range
Rust’s for
loop can also iterate over a range of numbers, which is especially useful for counting up or down.
Example: Iterating Over a Range
fn main() { for number in 1..4 { println!("The number is: {}", number); } }
Explanation:
- The
for
loop iterates over the range1..4
, printing the numbers 1 through 3. - Note that the range
1..4
is exclusive of 4.
5. Summary
In this lesson, we explored the different types of loops in Rust, each serving a unique purpose:
loop
: An unconditional loop that continues until explicitly stopped usingbreak
.while
: A conditional loop that continues as long as a condition is true.for
: A loop that iterates over collections or ranges, automatically handling iteration logic.
Understanding how and when to use each type of loop is crucial for controlling the flow of your Rust programs effectively. These loops are powerful tools for iterating over data, performing repetitive tasks, and managing complex control flows in your applications. In the next lesson, we will delve deeper into more advanced Rust features that build on these foundational concepts.