0

It is useful for functions to accept a dyn IntoIterator<blah> object, which allows you to use into_iter(), but that requires taking ownership of the collection.

It seems like Rust lacks a trait for the iter() method. Does something like the itertools crate provide a replacement?

Is there an trait for a resettable/restartable iterator?

Is there some alternative for a function that:

  1. Wants to iterate over a collection several times without cloning it.
  2. Does not want to take ownership of anything.

I guess I could take Iterator<Item=T>+Clone, but that's a bit ugly (I'd have to use the iterator before using it the first time).


I should add my actual goal: I would like to make a bunch of functions that can take both &[T] or &IndexSet<T> (from indexmap crate) as arguments.

1 Answers1

2

that requires taking ownership of the collection

No it does not, if the items can be references:

fn main() {
    let a = vec![1, 2, 3];
    do_it_twice_by_ref(&a);
    dbg!(a);
}

fn do_it_twice_by_ref<'a>(it: impl IntoIterator<Item = &'a u8> + Copy) {
    for i in it {
        dbg!(i);
    }
    for i in it {
        dbg!(i);
    }
}

This works because usually there is also a impl IntoIterator for &Collection (see here for IndexSet) which is implemented using the iter method. And Copy comes for free on shared references.

cafce25
  • 15,907
  • 4
  • 25
  • 31
  • This only allows me to iterate over the collection once. – user21952-is-a-great-name Feb 19 '23 at 21:34
  • Just add `Copy` to the constraints, shared references implement it anyways. – cafce25 Feb 19 '23 at 21:38
  • The now-edited version seems to work (thanks!). This is a little surprising to me, I'd expect the iterator to be exhausted after the first loop. It seems the compiler silently changes the first `it` to `it.copy()`, which is what it's supposed to do, but is curious here. – user21952-is-a-great-name Feb 19 '23 at 21:42
  • The first iterator is exhausted after the first loop, but since `it` didn't move (because it's `Copy`) the second loop just creates a new iterator with `into_iter` just like the first. – cafce25 Feb 19 '23 at 21:45
  • Sure, that makes sense. It just takes some familiarity with Rust to be used to the fact that the first `it` is the one that would have to be moved, and that moves are replaced with copies invisibly. Thank you again! – user21952-is-a-great-name Feb 19 '23 at 21:46
  • I understood your point a bit better. It's not the iterator that is copied, but the object with the IntoIter+Copy trait, such as &IndexSet. – user21952-is-a-great-name Feb 19 '23 at 23:59
  • You're right, fixed it. – cafce25 Feb 20 '23 at 04:19