diff --git a/text/0000-drain-range.md b/text/0000-drain-range.md new file mode 100644 index 00000000000..adbd22dcc15 --- /dev/null +++ b/text/0000-drain-range.md @@ -0,0 +1,91 @@ +- Start Date: 2015-01-12 +- RFC PR #: (leave this empty) +- Rust Issue #: (leave this empty) + +# Summary + +Replace `Vec::drain` by a method that accepts a range parameter. Add +`String::drain` with similar functionality. + +# Motivation + +Allowing a range parameter is strictly more powerful than the current version. +E.g., see the following implementations of some `Vec` methods via the hypothetical +`drain_range` method: + +```rust +fn truncate(x: &mut Vec, len: usize) { + if len <= x.len() { + x.drain_range(len..); + } +} + +fn remove(x: &mut Vec, index: usize) -> u8 { + x.drain_range(index).next().unwrap() +} + +fn pop(x: &mut Vec) -> Option { + match x.len() { + 0 => None, + n => x.drain_range(n-1).next() + } +} + +fn drain(x: &mut Vec) -> DrainRange { + x.drain_range(0..) +} + +fn clear(x: &mut Vec) { + x.drain_range(0..); +} +``` + +With optimization enabled, those methods will produce code that runs as fast +as the current versions. (They should not be implemented this way.) + +In particular, this method allows the user to remove a slice from a vector in +`O(Vec::len)` instead of `O(Slice::len * Vec::len)`. + +# Detailed design + +Remove `Vec::drain` and add the following method: + +```rust +/// Creates a draining iterator that clears the specified range in the Vec and +/// iterates over the removed items from start to end. +/// +/// # Panics +/// +/// Panics if the range is decreasing or if the upper bound is larger than the +/// length of the vector. +pub fn drain(&mut self, range: T) -> /* ... */; +``` + +Where `Trait` is some trait that is implemented for at least `Range`, +`RangeTo`, `RangeFrom`, `FullRange`, and `usize`. + +The precise nature of the return value is to be determined during implementation +and may or may not depend on `T`. + +Add `String::drain`: + +```rust +/// Creates a draining iterator that clears the specified range in the String +/// and iterates over the characters contained in the range. +/// +/// # Panics +/// +/// Panics if the range is decreasing, if the upper bound is larger than the +/// length of the String, or if the start and the end of the range don't lie on +/// character boundaries. +pub fn drain(&mut self, range: T) -> /* ... */; +``` + +Where `Trait` and the return value are as above but need not be the same. + +# Drawbacks + +- The function signature differs from other collections. +- It's not clear from the signature that `..` can be used to get the old behavior. +- The trait documentation will link to the `std::ops` module. It's not immediately apparent how the types in there are related to the `N..M` syntax. +- Some of these problems can be mitigated by solid documentation of the function itself.