31

Is there in Rust a Trait which supplies the iter() method? I only found the trait IntoIterator, which supplies into_iter().

Just to be clear here: I do not want the Iterator trait, which supplies next(), but a trait which supplies iter().

[ sidenote: Sometimes I'm very confused by the Rust libs. Iterator supplies next(), but IntoIterator supplies into_iter() (not supplying next() and for convention with moving), while IntoIter is a struct, that implements the Iterator trait (moving values). ]

Xolve
  • 22,298
  • 21
  • 77
  • 125
Tristan Storch
  • 690
  • 8
  • 18

1 Answers1

35

No, there is no trait that provides iter().

However, IntoIterator is implemented on references to some containers. For example, Vec<T>, &Vec<T> and &mut Vec<T> are three separate types that implement IntoIterator, and you'll notice that they all map to different iterators. In fact, Vec::iter() and Vec::iter_mut() are just convenience methods equivalent to &Vec::into_iter() and &mut Vec::into_iter() respectively.

fn foo(_x: std::slice::Iter<i32>) {}

fn main() {
    let v = vec![1, 2, 3];
    foo(v.iter());
    foo((&v).into_iter()); // iter() exists because this is awkward
}

If you want to write a function that is generic over containers that can be converted into an iterator that iterates over references, you can do so like this:

fn foo<'a, I: IntoIterator<Item=&'a i32>>(_x: I) {}

fn main() {
    let v = vec![1, 2, 3];
    foo(&v);
}
Francis Gagné
  • 60,274
  • 7
  • 180
  • 155
  • Wow. Thank you very much for this explanation. Combined with the link in the comment of starblue this is what I needed! – Tristan Storch Sep 25 '16 at 15:42
  • 1
    Why does rust not provide a trait with `iter()`? It sounds very useful, for example, if I want to have a struct that has a generic container as a member. `into_iter()` consumes the original container, and it would be useful to have a method that returns an iterator of references to the container without consuming it. – kmaork Nov 26 '20 at 15:58
  • @kmaork What this answer is saying is that it's not necessary: if you call `into_iter()` on a *shared reference* to a container, you'll get an iterator over references, the same as calling `iter()`. There's no need for a trait providing `iter()` when `IntoIterator::into_iter()` already solves that problem. Maybe what you need is a [higher-ranked trait bound](https://stackoverflow.com/q/35592750/234590)? – Francis Gagné Nov 26 '20 at 16:08
  • You say in your answer that "IntoIterator is implemented on references to some containers". Does that mean it is not implemented generically? If so, how is it possible to iterate over a generic container without consuming it? – kmaork Nov 26 '20 at 16:49
  • Every container type `T` needs to implement `IntoIterator` for references to `T`, there's no way around that. When you call `into_iter()` on a `&T`, you are "consuming" the reference, but that doesn't consume the underlying container. – Francis Gagné Nov 26 '20 at 17:10