Short question
Does already exist an iterator extension that returns a tuple with the Item
and the cloned iterator?
Long explanation
I was doing something pretty trivial, a nested iteration to take pairs of element in order to get the combinations. This can be easily done with the following:
let data: Vec<_> = (1..=10).collect();
let mut first_iter = data.iter();
while let Some(first) = first_iter.next() {
first_iter.clone().for_each(|second| {
println!("{}-{}", first, second);
})
}
Unfortunately, my brain really wants to use a more functional approach, something similar to the following:
let mut first_iter = data.iter();
first_iter.by_ref().for_each(|first| {
first_iter.clone().for_each(|second| {
println!("{}-{}", first, second);
});
});
This does not compile, just because first_iter
is mutable borrowed by the outer loop, and it cannot be borrowed again to create a clone.
Said that, I thought that an iterator extension to take an element and the clone of the iterator would be trivial. Something like this:
trait WithIterExt: Iterator + Clone {
fn with_iter(self) -> WithIter<Self> {
WithIter(self)
}
}
struct WithIter<Inner>(Inner);
impl<Inner> Iterator for WithIter<Inner>
where
Inner: Iterator + Clone,
{
type Item = (<Inner as Iterator>::Item, Inner);
fn next(&mut self) -> Option<Self::Item> {
self.0.next().map(|v| (v, self.0.clone()))
}
}
impl<I: Iterator + Clone> WithIterExt for I {}
This can be used in a very straightforward and rustic way:
data.into_iter().with_iter().for_each(|(v1, iter)| {
iter.for_each(|v2| {
println!("{}-{}", v1, v2);
});
});
My point is… it is too simple to not be around in some crate. I looked in itertools
but I did not find it. Do you know if this has been implemented somewhere? If not, maybe I will just open a PR for itertools
.
What do you think?