.iter()
IntoIterator
consumes self
to create an iterator.
This has its benefits: you get owned values from the iterator.
For example: if you call .into_iter()
on a Vec<Ticket>
you'll get an iterator that returns Ticket
values.
That's also its downside: you can no longer use the original collection after calling .into_iter()
on it.
Quite often you want to iterate over a collection without consuming it, looking at references to the values instead.
In the case of Vec<Ticket>
, you'd want to iterate over &Ticket
values.
Most collections expose a method called .iter()
that returns an iterator over references to the collection's elements.
For example:
#![allow(unused)] fn main() { let numbers: Vec<u32> = vec![1, 2]; // `n` has type `&u32` here for n in numbers.iter() { // [...] } }
This pattern can be simplified by implementing IntoIterator
for a reference to the collection.
In our example above, that would be &Vec<Ticket>
.
The standard library does this, that's why the following code works:
#![allow(unused)] fn main() { let numbers: Vec<u32> = vec![1, 2]; // `n` has type `&u32` here // We didn't have to call `.iter()` explicitly // It was enough to use `&numbers` in the `for` loop for n in &numbers { // [...] } }
It's idiomatic to provide both options:
- An implementation of
IntoIterator
for a reference to the collection. - An
.iter()
method that returns an iterator over references to the collection's elements.
The former is convenient in for
loops, the latter is more explicit and can be used in other contexts.
Exercise
The exercise for this section is located in 06_ticket_management/05_iter