Any reason not to implement filter/map/enumerate on IntoIterator types?


#1

One of the most common (if minor) frustrations I run into with Rust is refactoring iterator expressions. So for example, I might start with:

for item in vector {
  println!("{}", item);
}

Later on, I decide I need to know the index too:

for (index, item) in vector.enumerate() {
  println!("{}: {}", index, item);
}

… which of course does not compile, because enumerate is on Iterator and Iterator is not implemented for Vec.

So I was wondering if there was any technical or usability reason not to implement most of the Iterator methods on collections directly, and have them delegate through into_iter? With something like that, the refactoring above would be valid, and you wouldn’t need to call the iter method.

Thoughts?


#2

That’s because there’s vector.into_iter(), vector.iter() and vector.iter_mut() which give you 3 flavors of enumerate().

Direct implementation would either have to choose one, or be split into enumerate_owned() + enumerate_ref() + enumerate_ref_mut().

Edit: actually, it could also be solved by having .enumerate() implemented separately on slices, so vector.enumerate() and (&vector).enumerate() would be different.


#3

Yeah, I tried implementing this and I ended up having to write (&vector).enumerate() as you said. Which is pretty much just as inconvenient as changing &vector to vector.iter().


#4

There isn’t a fundemental reason this can’t happen, though it would cause some (mostly minor) namespace conflicts. For example, Option<T> implements IntoIterator but also has its own map method.

For now, the itertools crate provides functions like enumerate that take a generic IntoIterator, so that you can write:

for (index, item) in enumerate(vector) { ... }