Why Iterator.all does not consume the item?

In my understanding , the items are moved to the closure at A. Why I can move them again at B?

fn main() {
  struct U;
  let v = vec![U,U];
  let mut v = v.into_iter();
  v.all(|x|true);  // A moved
  v.all(|x|true);  // B iterate again
}

If you look at the docs you can see that all doesn't move the iterator. I presume this design is so that you can use it when you've only got a &mut.

1 Like

Another reason might be so you can still use everything after the first item to return false.

It might also be as simple as "because why not?"... There's no need to consume something if you don't have to.

3 Likes

In my understanding , into_iter will turn the Vec into an owned iterator (the items are transfered to the iterator , the iterator own them) so the the following is true

type of Self::Item is U

and the all callback has the following signature

F: FnMut(Self::Item) -> bool

call the callback will move the item, what I've missed?

The real answer is that at the second call to all iterator is already exhausted:

fn main() {
    #[derive(Debug)]
    struct U;
    let v = vec![U, U];
    let mut v = v.into_iter();
    v.all(|_: U| true); // all items moved
    println!("{:?}", v.collect::<Vec<_>>()); // prints []
}

Playground

1 Like

got it. really subtle. :grinning:

That justification doesn't make sense to me since there is already impl<'a, I> Iterator for &'a mut I where I: Iterator (and Iterator::by_ref which makes this convenient to use). I think the actual reason is that Iterator::any is short-circuiting, i.e. it returns after seeing the first true, and because self is not consumed you can keep iterating over any remaining items.

3 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.