1

Rust has a feature to drain an entire sequence,

If you do need to drain the entire sequence, use the full range, .., as the argument. - Programming Rust

Why would you ever need to drain the entire sequence? I can see this documented, but I don't see any use cases for this,

let mut drain = vec.drain(..);

If draining does not take ownership but clears the original structure, what's the point of not taking ownership? I thought the point of a mutable reference was because the "book was borrowed" and that you could give it back. If the original structure is cleared why not "own" the book? Why would you want to only borrow something and destroy it? It makes sense to want to borrow a subset of a vector, and clearing that subset -- but I can't seem to wrap my head around wanting to borrow the entire thing clearing the original structure.

Evan Carroll
  • 78,363
  • 46
  • 261
  • 468
  • 5
    Is there any reason why `..` *shouldn't* be supported as an argument? It would seem weird to me if you had a method like `drain` that accepts only non-full ranges. – trent Oct 07 '19 at 02:57
  • draining a vector is an efficient way to consume it if you don't need it after but you need some parts of its elements. – Denys Séguret Oct 07 '19 at 05:28
  • It looks like your question might be answered by the answers of [When should I use `drain` vs `into_iter`?](https://stackoverflow.com/q/27882800/155423). If not, please **[edit]** your question to explain the differences. Otherwise, we can mark this question as already answered. – Shepmaster Oct 07 '19 at 12:47
  • 1
    From the duplicate: *After using drain, the Vec is empty but the storage previously allocated for its elements remains allocated. This means that you can insert new elements in the Vec without having to allocate storage for them until you reach the Vec's capacity.* – Shepmaster Oct 07 '19 at 13:55
  • Possible duplicate of [When should I use \`drain\` vs \`into\_iter\`?](https://stackoverflow.com/questions/27882800/when-should-i-use-drain-vs-into-iter) – trent Oct 07 '19 at 13:58
  • That's cool, but if you're telling me the only reason to drain an entire sequence is internally memory reuse, that's fine but I don't see where that answer says that. – Evan Carroll Oct 07 '19 at 14:00
  • Not to strain the "book" metaphor too much: `into_iter` takes the book apart page by page, while `drain` scrapes the words off the pages so when it's done the book can be filled up later with something else. – trent Oct 07 '19 at 14:02
  • @trentcl so if you're not reusing the memory, the answer is that there is no advantage and you shouldn't use `drain` (because it's all about memory reuse). I don't see that on the other question, and think it would be a valuable contribution. – Evan Carroll Oct 07 '19 at 14:04
  • 1
    I don't agree. "What are the appropriate uses for each iterator?" encompasses your question and the answers are pretty much exhaustive. We don't need to clarify every "What's the difference between X and Y?" with a new question that asks "Are these the *only* differences between X and Y?" – trent Oct 07 '19 at 16:02

1 Answers1

0

I think you are approaching this question from the wrong direction.

Having made a decision that you would like to have a drain method that takes a RangeBounds, you then need to consider the pros and cons of disallowing an unbounded RangeBounds.

Pros

  • If you disallowed an unbounded range, there would be less confusion about whether to use drain(..) vs into_iter(), although noting that these two are not exactly identical.

Cons

  • You would actually have to go out of your way to disallow an unbounded range.

  • Ideally, you would want the use of an unbounded range to cause a compilation error. I'm new to Rust so I am not certain of this, but as far as I know there is no way to express that drain should take a generic that implements trait RangeBounds as long as it is not a RangeFull.

  • If it could not be checked at compile time, what behavior would you want at runtime? A panic would seem to be the only option.

  • As observed in the comments and in the proposed duplicate, after completely draining it, the Vec will have a length of 0 but a capacity the same as it did before calling drain. By allowing an unbounded range with drain you are making it easier to avoid a repeated memory allocation in some use cases.

To me at least, the cons outweigh the pros.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
harmic
  • 28,606
  • 5
  • 67
  • 91
  • One could create a separate trait that only the desired concrete range types would implement, but that adds the problem of a new, different trait. – Shepmaster Oct 09 '19 at 23:25