Nugget 9
Home
You write for x in vec and it just works. But what's actually
happening? An iterator is anything that knows how to produce items one at a
time — and nearly everything in Rust can become one.
Iterator TraitAt its core, an iterator is anything that implements this trait:
trait Iterator {
type Item;
fn next(&mut self) -> Option<Self::Item>;
}
That's it. One method, next(). It returns:
Some(item) — there's another valueNone — the iteration is finishedlet v = vec![10, 20, 30]; let mut iter = v.iter(); // get an iterator assert_eq!(iter.next(), Some(&10)); assert_eq!(iter.next(), Some(&20)); assert_eq!(iter.next(), Some(&30)); assert_eq!(iter.next(), None); // end of the road
for Loop Is Sugar
Every for loop is secretly a call to .next():
// What you write:
for item in &v {
println!("{item}");
}
// What the compiler generates:
let mut iter = v.iter();
while let Some(item) = iter.next() {
println!("{item}");
}
The while let Some pattern is idiomatic Rust — it unwraps the
Option and exits the loop when None is returned.
A Vec can produce three different kinds of iterators depending on
how you access it:
let v = vec!["a".to_string(), "b".to_string(), "c".to_string()];
// 1. Immutable borrow — gives &T
for item in &v { // calls v.iter()
println!("{item}"); // item: &String
}
println!("v is still usable: {:?}", v);
// 2. Mutable borrow — gives &mut T
for item in &mut v { // calls v.iter_mut()
item.push_str("!");
}
println!("v now: {:?}", v);
// 3. Consume — gives T, v is gone
for item in v { // calls v.into_iter()
println!("{item}"); // item: String (owned)
}
// println!("{:?}", v); // ❌ v was moved!
| Loop syntax | Method | Yields | Original usable? |
|---|---|---|---|
for x in &v |
iter() |
&T |
✅ Yes |
for x in &mut v |
iter_mut() |
&mut T |
✅ Yes (after borrow ends) |
for x in v |
into_iter() |
T (owned) |
❌ No, consumed |
Ranges, strings, slices, HashMap, files — they all produce iterators:
// Range
for i in 0..5 { println!("{i}"); } // 0 1 2 3 4
// String chars
for c in "hello".chars() { print!("{c} "); } // h e l l o
// Array slice
let arr = [10, 20, 30];
for x in &arr { println!("{x}"); }
// Lines from a string
let text = "a\nb\nc";
for line in text.lines() { println!("{line}"); }
next() method returning Option<Item>.for loops are syntactic sugar for calling next() in a loop.&collection → iter() → borrows, collection → into_iter() → consumes.Vec.