Looping Through a Collection with for
You can choose to use the while
construct to loop over the elements of a collection, such as an array. For example, the loop in Listing 3-4 prints each element in the array a
.
Filename: src/main.rs
fn main() {
let a = [10, 20, 30, 40, 50];
let mut index = 0;
while index < 5 {
println!("the value is: {}", a[index]);
index += 1;
}
}
Listing 3-4: Looping through each element of a collection using a while
loop
Here, the code counts up through the elements in the array. It starts at index 0
, and then loops until it reaches the final index in the array (that is, when index < 5
is no longer true
). Running this code will print every element in the array:
$ cargo run
Compiling loops v0.1.0 (file:///projects/loops)
Finished dev [unoptimized + debuginfo] target(s) in 0.32s
Running `target/debug/loops`
the value is: 10
the value is: 20
the value is: 30
the value is: 40
the value is: 50
All five array values appear in the terminal, as expected. Even though index
will reach a value of 5
at some point, the loop stops executing before trying to fetch a sixth value from the array.
However, this approach is error prone; we could cause the program to panic if the index value or test condition is incorrect. For example, if you changed the definition of the a
array to have four elements but forgot to update the condition to while index < 4
, the code would panic. It's also slow, because the compiler adds runtime code to perform the conditional check of whether the index is within the bounds of the array on every iteration through the loop.
As a more concise alternative, you can use a for
loop and execute some code for each item in a collection. A for
loop looks like the code in Listing 3-5.
Filename: src/main.rs
fn main() {
let a = [10, 20, 30, 40, 50];
for element in a {
println!("the value is: {element}");
}
}
Listing 3-5: Looping through each element of a collection using a for
loop
When we run this code, we'll see the same output as in Listing 3-4. More importantly, we've now increased the safety of the code and eliminated the chance of bugs that might result from going beyond the end of the array or not going far enough and missing some items.
Using the for
loop, you wouldn't need to remember to change any other code if you changed the number of values in the array, as you would with the method used in Listing 3-4.
The safety and conciseness of for
loops make them the most commonly used loop construct in Rust. Even in situations in which you want to run some code a certain number of times, as in the countdown example that used a while
loop in Listing 3-3, most Rustaceans would use a for
loop. The way to do that would be to use a Range
, provided by the standard library, which generates all numbers in sequence starting from one number and ending before another number.
Here's what the countdown would look like using a for
loop and another method we've not yet talked about, rev
, to reverse the range:
Filename: src/main.rs
fn main() {
for number in (1..4).rev() {
println!("{number}!");
}
println!("LIFTOFF!!!");
}
This code is a bit nicer, isn't it?