Ever wanted to write this kind of code ?
fn main ()
{
let mut iterator = (0 .. 10).into_iter();
for x in iterator.take(3) {
println!("{} is in the podium!", x);
};
for x in iterator {
println!("{} is not, but maybe next time?", x);
};
}
Obviously it cannot work since .take(n)
takes (duh) ownership of iterator
.
This can however be fixed by (mutably) borrowing iterator
for the time of that first iteration:
fn main ()
{
let mut iterator = (0 .. 10).into_iter();
for x in (0 .. 3).filter_map(|_| iterator.next()) { // `FnMut` closure captures `&mut iterator`
println!("{} is in the podium!", x);
}; // &mut iterator is dropped here
for x in iterator {
println!("{} is not, but maybe next time?", x);
};
}
The mutable borrow (stored in the .filter_map()
closure environment) is released at the end of the iteration and thus we didn't lose ownership of \iterator`; that's why we are perfectly able to give it to the second iteration.
However, such tricks
- may not be known/understood by beginners,
- are definitely not very readable / idiomatic
Hence my suggestion of a .fetch(n)
method:
fn main ()
{
let mut iterator = (0 .. 10).into_iter();
for x in iterator.fetch(3) { // captures `&mut iterator`
println!("{} is in the podium!", x);
}; // &mut iterator is dropped here
for x in iterator {
println!("{} is not, but maybe next time?", x);
};
}
The only remaining question is whether or not to ensure that those n
elements are always consumed by the Fetch
iterator, in case of, for instance, a break
.
Here is a suggestion of a .fetch(n)
implementation where those n
first values are not acessible by the main iterator
no matter how the iteration went: Rust Playground
If the break
-to-avoid-consumption behavior is preferred, simply comment the Drop
trait implementation (I guess there could be both a .fetch(n)
and .fetch_upto(n)
methods to give the caller the option to chose the appropriate behavior)