Rust For Loops
Rust's for loop iterates over anything that implements IntoIterator, from simple numeric ranges to entire collections, without manual indexing or off-by-one bugs.
Iterating Over a Range
A range like 0..5 is half-open and excludes its upper bound, producing 0, 1, 2, 3, 4. Adding an equals sign, as in 0..=5, makes the range inclusive of the final value.
Exclusive vs inclusive ranges
fn main() {
for i in 0..5 {
println!("i = {}", i);
}
for i in 1..=5 {
print!("{} ", i);
}
println!();
}Iterating Over Collections
Writing for item in &collection borrows each element by reference, leaving the collection usable afterward. Writing for item in collection (without the &) takes ownership of the collection and consumes it.
Borrowing and enumerating a Vec
fn main() {
let fruits = vec!["apple", "banana", "cherry"];
for fruit in &fruits {
println!("I like {}", fruit);
}
for (index, fruit) in fruits.iter().enumerate() {
println!("{}: {}", index, fruit);
}
}Note: Reach for .enumerate() whenever you need both the index and the value inside a loop — it's clearer and less error-prone than maintaining a separate counter variable by hand.
for Loops and Ownership
Note: for item in collection (without &) moves the collection into the loop, so it can't be used again afterward unless its element type is Copy. Default to iterating by reference unless you specifically intend to consume the values.
Reversing and stepping through a range
fn main() {
for i in (0..10).step_by(2) {
print!("{} ", i);
}
println!();
for i in (1..=5).rev() {
print!("{} ", i);
}
println!();
}- Ranges are half-open by default (0..5 excludes 5); add = for an inclusive range (0..=5).
- for item in &collection borrows; for item in collection takes ownership.
- Iterator adapters like .rev(), .step_by(), and .enumerate() compose before the loop consumes them.
- for loops never panic on out-of-bounds access, because they never index manually.
Exercise: Rust For Loops
What does the range `0..5` include when used in `for i in 0..5`?