Mutable iterator
We iterate through iterator elements by calling next on it - this means we need to maintain the iterator's state. Folloing is a
struct that mutabley borrows the underlying list and stores it. The life time paramter 'a is there
because we are holding a reference to the list - we don't own the list. An IntoIterator
instance
can exist only as long as unerlying list struct instance is alive. The iterator can not outlive the
list struct instance that it is borrowing.
pub struct IntoIterator<'a, T: std::fmt::Debug + Default + Clone + PartialEq> {
list: &'a mut List<T>,
}
Getting an IntoIterator instance:
We have added following function to the List
struct to return an IntoIterator
instance. While
returning the IntoIterator
struct instance - list passes it its own mutable self reference. And
because we have a mutable reference to the list - we can modify it as long as we return it back in
some shape - either intact or altered.
pub fn into_iter(&mut self) -> IntoIterator<'_, T> {
//Taking a mutable reference to the list
IntoIterator { list: self }
}
Node: We are breaking rust's convention here. Idiomatic rust consumes the collection as a whole if elements are dropped while iterating. Here we are not destroying the list though post iteration it bcomes empty. We could have consumed the list instead.
Now that we have struct that we have named IntoIterator
and it has a mutable list inside it - can
we iterate over the elements inside the list? Not yet. We have not added the iterator behaviour to
our struct yet. We need to implement the Iterator trait for our IntoIterator
struct for that. Whichis what we will do next.
Note: The
Iterator
trait has quite a bunch of methods defined in it. But we need to implement only thenext
method of it because rests are implemented based onnext
.
Implement Iterator for IntoIterator:
//Iterator that consumes the list elements from the front
impl<'a, T: std::fmt::Debug + Default + Clone + PartialEq> Iterator for IntoIterator<'a, T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
self.list.pop_front()
}
}
Our implementation could not have been any more simpler than this - we just pop the elements from the front!