In Rust, the entire standard collection library is built on the concept of iterators. An iterator is an object that implements the Iterator trait, which defines the next() method. This method returns the next item in the data sequence (Option<T>, where Some(T) is the next value, and None signifies the end of the sequence).
Example of a standard iterator:
let v = vec![1, 2, 3]; let mut iter = v.iter(); while let Some(x) = iter.next() { println!("{}", x); }
Iterator adaptors are methods (like .map(), .filter(), .enumerate(), .take()) that return new iterators that process values "on the fly" according to provided functions.
Custom iterators are implemented by creating a structure and implementing the Iterator trait for it with custom behavior:
struct Counter { count: u8 } impl Iterator for Counter { type Item = u8; fn next(&mut self) -> Option<Self::Item> { if self.count < 5 { self.count += 1; Some(self.count) } else { None } } }
Use standard adaptors when they are sufficient for processing collections. Implementing a custom iterator is necessary if:
Can you create infinite iterators? What would happen if you tried to collect them into a collection, for example, using
.collect()?
Answer: Yes, in Rust there are iterators like std::iter::repeat, which return an infinite sequence:
let mut endless = std::iter::repeat(1); endless.next(); // will return Some(1) indefinitely
If you try to collect such an iterator into a collection using .collect(), the program will hang or crash with a memory overflow because the iteration will not terminate on its own!
Story
In a REST API project, an array of 1000 elements was sorted, and then .iter().filter(|x| *x > 500) was used, but instead of .collect::<Vec<_>>(), they applied .fold(0, |acc, _| acc + 1) inside a complex adaptor, losing the understanding of whether the iteration would complete correctly. The result: random hangs due to the filtering occurring on an unrestricted lazy iterator with an internal error.
Story
In a proprietary engine for generating unique IDs, a random developer decided to implement their own iterator, forgetting to return None when reaching the limit. As a result, the iteration went into an infinite loop, the production server consumed all CPU and did not respond to requests.
Story
In the frontend part (WebAssembly module), an iterator with nested adaptors: .map().filter().skip() was used, and they tried to obtain the result through .collect() for a form. When changing the type under the adaptor, Rust produced a complex compile-time error about type mismatches because they forgot to specify the exact type of the collection: .collect::<Vec<_>>(). The problem was solved by adding an annotation, but they spent several hours searching for the cause.