How Rust's for loop works
In many languages a for loop has three parts in its header: a starting statement, a condition and an update. Rust's for loop does not. It takes a variable name and something it can iterate over, and runs the body once for each item that comes out:
for i in range {
// statements
}
The start, the end and the step are all carried by the thing after in. For counting, that is a range, and the loop variable receives one value from the range on every pass. You do not declare the variable with let, you do not test a condition and you do not write an update. All three are handled for you.
Ranges
A range is written with two dots. 0..4 produces 0, 1, 2 and 3. The start is included and the end is excluded. With an equals sign, 0..=4 includes the end as well and produces 0, 1, 2, 3 and 4.
for i in 0..4 {
println!("Hello world! {}", i);
}
This runs four times, with i equal to 0, 1, 2 and 3, and prints Hello world! 0 through Hello world! 3. A useful number to remember: for a..b the body runs b - a times, and for a..=b it runs b - a + 1 times (when b is not below a).
What the for loop does for you
Compare it with a while loop that does the same job:
let mut i = 0;
while i < 4 {
println!("Hello world! {}", i);
i += 1;
}
The while version has three separate places where a mistake can hide: the starting value, the condition and the update. The for version has one: the range. There is no way to forget the update, so a for loop over a range cannot run forever.
The loop variable exists only inside the loop. Using i after the closing brace is a compile error, cannot find value i in this scope. It is also a fresh variable on each pass, so changing it inside the body does not change how the loop counts. Writing to it would need for mut i in ..., and the next value still comes from the range.
The exercise, step by step
The lesson asks for the message I promise to learn coding. printed five times using a for loop.
- Write the loop header with a variable
iover the range0..5. The range produces 0, 1, 2, 3 and 4, which is five values. Since the end is excluded,0..5is exactly right. Using0..=5would produce six values and print the message six times. - Print the message inside the braces with
println!. The body runs once per value, so one line of code prints the message five times.
for i in 0..5 {
println!("I promise to learn coding.");
}
The program prints the message on five lines.
The unused variable warning
The body never uses i, so Rust prints a warning, unused variable: i, and suggests naming it _i. It is only a warning, and the program still compiles and runs. When you do not need the number, you can write _ as the name, as in for _ in 0..5. That says "I do not need this value" and the warning goes away. The lesson's exercise keeps i, and the output is the same.
Common mistakes
- Mixing up
..and..=.0..5runs five times and0..=5runs six times. - Looking for a condition or an update. There is none to write. If you need a different start, end or step, you change the range, or use methods on it, which the next lessons show.
- Writing parentheses around the range out of habit from other languages. They are not needed (they are used later only for calling methods on a range).
- Using the loop variable outside the loop. It no longer exists after the closing brace.
- A backwards range.
5..0is empty, so the body never runs. A Rust range only counts up.
Key takeaways
for i in range { ... }runs the body once for each value in the range, with no counter to declare, test or update.a..bexcludesbanda..=bincludes it.- A
forloop over a range always finishes, because the range is finite. - Name the variable
_if the body does not use it.
