Add Iterator::into_vec()

Though we have nice Iterator::collect(), the most common use cases of this method as I’ve seen are my_iter.collect::<Vec<_>>(), which is a bit complicated to type. So it would be worth to add this simple shortcut method for it.

#[inline]
fn into_vec(self) -> Vec<Self::Item> {
    self.collect::<Vec<_>>()
}

Previous discussion on this topic can be found here.

4 Likes

Yes, having to add :Vec<_> is a bit annoying.

Itertools has a convenience method for it too, which I think indicates that there’s a demand: https://docs.rs/itertools/0.5.9/itertools/trait.Itertools.html#method.collect_vec

I too, would really like this. I frequently import itertools just for the collect_vec helper.

collect_vec seems to be one of the more popular methods in itertools (if popularity feelings tell us anything). Best methods from itertools should move into libstd somehow.

A change of this calibre (it’s a small new feature) should be eligible to just be filed as an implementation in a PR to Rust and the libs team can discuss inclusion as an unstable feature. However before that:

This doesn’t seem to be feasible to add to Iterator, because the Iterator trait is in libcore, and can’t use Vec which is in a higher crate (libcollections). Do you see any way to get around this?

I've written some comments in the closed thread.

This feature goes according to:

I’d rather just get default type parameters working but that’s probably significantly harder.

Can you please write me an example of what you mean?

With default type parameters, it could be:

fn collect<B = Vec<Self::Item>>(self) -> B
    where B: FromIterator<Self::Item>

(except we still have the problem that core::iter::Iterator doesn’t know Vec)

4 Likes

Couldn’t libstd have trait StdIteratorExt: Iterator, with a blanket impl on T: Iterator, and export it in prelude?

1 Like

Maybe we could turn it around and add Vec::from_iter()? That could get around the core/std issue at least.

I don’t know how collect() works today, but it would sure be nice if, for Iterators that know about their size, the Vec could allocate to the required capacity in one go.

Vec::from_iter exists, and its exactly how collect works, in fact. Vec implements FromIterator, and collect has the signature fn collect<T>(self) -> T where T: FromIterator<Self::Item>.

Return type polymorphism is a powerful advantage of the trait system over similar kinds of polymorphism & collect is the most common ‘entry point’ to understanding that idea - that you can collect into vectors or hashmaps or strings with the same method. I haven’t found the turbofish too annoying, but YMMV.

2 Likes

Personally, I love the method collect() for the same reason that @withoutboats wrote. I think every rust programmer take a look at how exactly .collect() works. But since many of us type .collect::<Vec<_>>() everyday and feels uncomfortable, it would be nice to add a sugar method for this common use case.

Anyway @sgrif 's idea seems promising to me. Is there some other case like this in std?

I don't know how collect() works today, but it would sure be nice if, for Iterators that know about their size, the Vec could allocate to the required capacity in one go.

std already does this with the size_hint method.

Yep, and it has some specialization tricks to make collect extra good if the iterator is “trusted” to report a correct exact size.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.