3

On page 327 of Programming Rust you can find the following statement

However, unlike the into_iter() method, which takes the collection by value and consumes it, drain merely borrows a mutable references to the collection, and when the iterator is dropped, it removes any remaining elements from the collection, and leaves it empty.

I'm confused at what it means it says it removes any remaining elements from the collection? I can see with this code when the iterator is dropped the remaining elements from a are still there,

fn main() {
    let mut a = vec![1, 2, 3, 4, 5];
    {
        let b: Vec<i32> = a.drain(0..3).collect();
    }

    println!("Hello, world! {:?}", a);
}

Perhaps I'm confused at merely the wording. Is there something more to this?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Evan Carroll
  • 78,363
  • 46
  • 261
  • 468
  • There isn't a single `drain` method but rather a separate one for many kinds of collections e.g. `Vec`, `HashMap` and `String`. Does *Programming Rust* say which one it's talking about, or is it left ambiguous? [`HashSet::drain`](https://doc.rust-lang.org/stable/std/collections/struct.HashSet.html#method.drain) does exactly what the text says. – SCappella Oct 07 '19 at 03:02
  • And there is `drain_filter`, which is also implemented by `BTreeMap` and `BTreeSet`, both not imlementing `drain`. – Wolfgang Kuehn Mar 09 '22 at 14:42

1 Answers1

7

This looks like a bit imprecise wording.

The real meaning of these words is: if you drop the drain iterator without exhausting it, it will drop all the elements used for its creation. As you've asked it to use only the first three elements, it won't empty the entire vector, but rather the first part only; but it will do this even if unused:

fn main() {
    let mut a = vec![1, 2, 3, 4, 5];
    {
        let _ = a.drain(0..3);
    }

    println!("Hello, world! {:?}", a);
}
Hello, world! [4, 5]

playground

You could understand this in the following way: the "collection" mentioned here is not the initial collection the drain was called on, but rather is "sub-collection", specified by the passed range.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Cerberus
  • 8,879
  • 1
  • 25
  • 40