Counting with a while loop
A while loop is a good tool for producing a sequence of numbers. You pick a starting value, a condition that says when to stop, and a step that moves the counter forward. This lesson is about the first two: the initialization and the condition.
Here is a loop that prints the numbers from 0 through 4:
let mut i = 0;
while i < 5 {
println!("{}", i);
i += 1;
}
Its output:
0
1
2
3
4
How the loop runs
Trace the values of i:
istarts at 0. The test0 < 5is true, so the body prints 0 andibecomes 1.- The same happens for 1, 2, 3 and 4, and
iends the fifth pass as 5. - The test
5 < 5is false, so the loop ends without printing 5.
The loop starts with the value you give it and stops before the first value that fails the test. That is why 5 is never printed.
Choosing the start and the condition
The two numbers that matter are where the counter begins and how the condition compares it to the limit.
- The initial value is the first number printed, because the body runs before the counter changes.
<against<=decides whether the limit itself is printed. Withi < 5the last printed value is 4. Withi <= 5it is 5.
To print 3 through 10, the first value is 3 and the last printed value is 10, so the condition must still be true when the counter equals 10. That means <= 10 (or, equivalently, < 11). Writing < 10 would stop at 9, which is the most common slip in these exercises.
The exercise, step by step
The lesson asks you to print all the numbers from 3 to 10 with a while loop.
- Declare the counter with
let mut counter = 3;. It must bemut, because the loop will change it, and it starts at 3 because 3 is the first number to print. - Write the loop with the condition
counter <= 10. In Rust there are no parentheses around the condition, and the braces are required. Using<=means 10 itself is printed. - Print the counter with
println!("{}", counter);. The{}is a placeholder that is replaced by the next argument, andprintln!ends the line, so each number is on its own line. It is a macro, so the!is part of its name. - Add 1 to the counter with
counter += 1;. Without it,counterwould stay 3 forever and the loop would never end. Rust has no++operator.
let mut counter = 3;
while counter <= 10 {
println!("{}", counter);
counter += 1;
}
It prints the eight numbers 3, 4, 5, 6, 7, 8, 9 and 10, one per line.
Counting how many times it runs
For a counter that goes up by 1, the number of passes is the last value minus the first, plus one. From 3 through 10 that is 10 - 3 + 1 = 8. Checking this number against what the loop prints is a quick way to catch an off-by-one mistake.
Common mistakes
- Printing before or after the update. If
counter += 1;comes beforeprintln!, the first number printed is 4, and 11 is printed at the end. Print first, then update, when you want the starting value to appear. - Using
<where the limit should be included, which drops the last number. - Forgetting
mut. The compiler reportscannot assign twice to immutable variableand suggestslet mut. - Forgetting the update, which prints 3 forever.
Key takeaways
- The initial value of the counter is the first number the loop prints.
- The condition decides where the loop stops:
<excludes the limit and<=includes it. println!("{}", x)prints the value ofxand a newline.- The counter must be declared with
let mutand updated with+= 1inside the loop.
