I have an Iterator implementation that looks like this:
struct MyType {
// stuff
}
struct Snapshot {
// stuff
}
impl MyType {
pub fn iter(&mut self) -> MyIterator {
MyIterator {
foo: self
}
}
}
struct MyIterator<'a> {
foo: &'a mut MyType
}
impl<'a> Iterator for MyIterator<'a> {
type Item = Snapshot;
fn next(&mut self) -> Option<Self::Item> {
if self.cheap_condition() {
self.cheap_mutation(); // Inexpensive
let s: Snapshot = self.snapshot(); // Expensive copying
Some(s)
} else {
None
}
}
}
This works fine if I want to use every instance of Snapshot generated, but if I want to use something like Iterator::step_by or Iterator::last, where I don't care about the intermediate Snapshots, the cost incurred by the generation of those unused values is a massive performance hit.
I could override every single method of Iterator such that the expensive operation only takes place when necessary, but I feel like there must be a simpler and more idiomatic way of doing this, or a way to lazily generate the Snapshot corresponding to an iteration from an intermediate type for Item if Iterator::next hasn't been called again.
I do not want to return references to MyType, because I want the Snapshots that I do generate to have independent lifetimes, enabling, for example, the result of Iterator::collect() to outlive the instance of MyType.
You don't have to override every
Iteratormethod. The only relevant ones arenth,last,count,step_by, andskip. All the other methods require examiningSelf::Itemin some way so you can't avoid generatingSnapshots for those. Luckilystep_byandskipusenthinternally, so that really only leaves us withnth,count, andlastwhich we must override:playground
If you want to make other
Iteratormethods likefilterlazy by checking the predicate againstMyType<'a>instead ofSnapshotyou have to define your ownIterator-like trait for that, as all the other methods only work onSelf::Item.