Counting backwards
A Rust range only counts upward. If you write a range whose start is above its end, such as 5..=-5, the range is empty, and a for loop over it never runs its body. To count down, you build the ascending range and then reverse it with the method rev().
for i in (3..=7).rev() {
println!("{}", i);
}
This prints 7, 6, 5, 4 and 3, one per line. The range 3..=7 holds 3, 4, 5, 6, 7 in that order, and rev() hands them out from the other end.
What rev() does
rev() does not change the numbers in the range. It only changes the order in which the loop receives them. The start and the end of the range are the same as before, so the same rules apply:
- The range's lower bound is where the countdown ends, and its upper bound is where it starts.
(3..=7).rev()starts at 7 and ends at 3.(3..8).rev()gives exactly the same numbers, because the upper bound 8 is excluded, so the first value is 7.
So to count down from a to b, build the range b..=a and reverse it. This is a common way to get confused: the lower number comes first in the range, even though the loop prints the higher number first.
Why the parentheses are required
A method call binds tighter than the ..= operator. Writing -5..=5.rev() means "call rev on the number 5" and then build a range from the result. The compiler rejects it with can't call method rev on type {integer} and suggests wrapping the range in parentheses. So always write (-5..=5).rev().
The exercise, step by step
The lesson asks you to print all the numbers from 5 down to -5, in decreasing order, using a variable called number.
- Build the ascending range from the lowest value to the highest:
-5..=5. The=includes 5 at the top end. The negative number needs no special syntax. - Wrap it in parentheses and call
.rev(), so the loop meets 5 first and -5 last. - Write the loop as
for number in (-5..=5).rev(). - Print
numberin the body withprintln!("{}", number);. The{}placeholder is replaced by the value.
for number in (-5..=5).rev() {
println!("{}", number);
}
It prints 5, 4, 3, 2, 1, 0, -1, -2, -3, -4 and -5 on eleven lines. The count is 5 - (-5) + 1 = 11.
Using rev() with a step
You can combine it with step_by to count down in larger steps. Put rev() first, then step_by:
for i in (0..=10).rev().step_by(5) {
println!("{}", i);
}
This prints 10, 5 and 0. The reversed range starts at 10, and every fifth value after it is kept.
Common mistakes
- Writing the range backwards.
5..=-5is empty and prints nothing. The compiler does not complain. - Forgetting the parentheses around the range before
.rev(). - Using
..when the end must be included.(-5..5).rev()starts at 4, not 5. - Counting down with unsigned numbers. A
forloop withrev()is the safe way to count down to 0 with a type likeusize. For example,(0..n).rev()visits n-1 down to 0 and stops. A manualwhile i >= 0loop with an unsigned counter can never end, because the counter cannot go below 0.
Key takeaways
- Ranges only count up. To go down, reverse an ascending range with
.rev(). - Write the range from the low end to the high end, and wrap it in parentheses before calling a method on it.
..=includes the high end, which is the first value of a reversed loop.- Combine
.rev()with.step_by(n), in that order, for a countdown with larger steps.
