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 Snapshot
s, 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 Snapshot
s 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
Iterator
method. The only relevant ones arenth
,last
,count
,step_by
, andskip
. All the other methods require examiningSelf::Item
in some way so you can't avoid generatingSnapshot
s for those. Luckilystep_by
andskip
usenth
internally, so that really only leaves us withnth
,count
, andlast
which we must override:playground
If you want to make other
Iterator
methods likefilter
lazy by checking the predicate againstMyType<'a>
instead ofSnapshot
you have to define your ownIterator
-like trait for that, as all the other methods only work onSelf::Item
.