Is there an Iterator-like trait which returns refe

2020-02-14 08:49发布

问题:

This would make it possible to safely iterate over the same element twice, or to hold some state for the global thing being iterated over in the item type.

Something like:

trait IterShort<Iter>
    where Self: Borrow<Iter>,
{
    type Item;

    fn next(self) -> Option<Self::Item>;
}

then an implementation could look like:

impl<'a, MyIter> IterShort<MyIter> for &'a mut MyIter {
    type Item = &'a mut MyItem;

    fn next(self) -> Option<Self::Item> {
        // ...
    }
}

I realize I could write my own (I just did), but I'd like one that works with the for-loop notation. Is that possible?

回答1:

The std::iter::Iterator trait can not do this, but you can write a different trait:

trait StreamingIterator {
    type Item;
    fn next<'a>(&'a mut self) -> Option<&'a mut Self::Item>;
}

Note that the return value of next borrows the iterator itself, whereas in Vec::iter for example it only borrows the vector.

The downside is that &mut is hard-coded. Making it generic would require higher-kinded types (so that StreamingIterator::Item could itself be generic over a lifetime parameter).

Alexis Beingessner gave a talk about this and more titled Who Owns This Stream of Data? at RustCamp.

As to for loops, they’re really tied to std::iter::IntoIterator which is tied to std::iter::Iterator. You’d just have to implement both.



回答2:

The standard iterators can't do this as far as I can see. The very definition of an iterator is that the outside has control over the elements while the inside has control over what produces the elements.

From what I understand of what you are trying to do, I'd flip the concept around and instead of returning elements from an iterator to a surrounding environment, pass the environment to the iterator. That is, you create a struct with a constructor function that accepts a closure and implements the iterator trait. On each call to next, the passed-in closure is called with the next element and the return value of that closure or modifications thereof are returned as the current element. That way, next can handle the lifetime of whatever would otherwise be returned to the surrounding environment.