Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When should I use `drain` vs `into_iter`?

Tags:

iterator

rust

On the surface, it looks like both drain and into_iter provide similar iterators, namely over the values of the collection. However, they are different:

fn main() {     let mut items1 = vec![0u8, 1, 2, 3, 4, 5, 6, 7, 8, 9];     let items2 = items1.clone();      println!("{:?}", items1.drain().count());     println!("{:?}", items2.into_iter().count());      println!("{:?}", items1);     // println!("{:?}", items2); Moved } 

drain takes a &mut to the collection and the collection is available afterwards. into_iter consumes the collection. What are the appropriate uses for each iterator?

like image 816
Shepmaster Avatar asked Jan 11 '15 00:01

Shepmaster


1 Answers

They are somewhat redundant with each other. However, as you say, Drain just borrows the vector, in particular, it has a lifetime connected with the vector. If one is wishing to return an iterator, or otherwise munge iterators in the most flexible way possible, using into_iter is better, since it's not chained to the owner of the originating Vec. If one is wishing to reuse the data structure (e.g. reuse the allocation) then drain is the most direct way of doing this.

Also, a (somewhat) theoretical concern is that Drain needs to result in the originating structure being a valid instance of whatever type it is, that is, either preserve invariants, or fix them up at the end, while IntoIter can mangle the structure as much as it likes, since it has complete control of the value.

I say only "somewhat" theoretical because there is a small, real world example of this in std already: HashMap exposes .drain and .into_iter via its internal RawTable type, which also has those methods. into_iter can just read the hash of the value being moved directly and that's that, but drain has to be careful to update the hash to indicate that the cell is then empty, not just read it. Obviously this is absolutely tiny in this instance (probably only one or two additional instructions) but for more complicated data structures like trees there may be some non-trivial gains to be had from breaking the invariants of the data structure.

like image 98
huon Avatar answered Sep 28 '22 07:09

huon