Proposal
Problem statement
VecDeque currently allows truncating down to a specific length via dropping elements from the front (truncate_front) or the back (truncate), but it lacks a way to specify a range that should be kept while truncating the rest (which might truncate both ends).
Motivating examples or use cases
A system collects metrics during a period in which a benchmark is run, but collection inevitably starts before the load is applied and continues for some time after it ends. Let's clip off those pre- and post-test data points before analyzing the results.
// example data
let mut metrics = [0, 0, 0, 1, 2, 3, 2, 1, 0, 0].iter().collect::<VecDeque<_>>();
// during collection, push_back; truncate_front is called to ensure events don't grow without bound
// if the metric is zero, assume the test either had not yet started or had already ended
let start = metrics.iter().position(|&&x| x > 0).unwrap_or_default();
let end = metrics.iter().rposition(|&&x| x > 0).unwrap_or_default() + 1;
// metrics.truncate_to_range(start..end);
metrics.truncate(end);
metrics.truncate_front(metrics.len() - start);
assert!(metrics.into_iter().eq([1, 2, 3, 2, 1].iter()));
for x in metrics.iter() {
// analysis...
}
Other ideas:
Solution sketch
pub fn truncate_to_range<R>(&mut self, range: R)
where
R: RangeBounds<usize>,
{
// Implementation largely similar to truncate/truncate_front.
//
// (1) validate range
// (2) try to reduce to no-op, clear, truncate, or truncate_front
// (3) otherwise, compute up to three regions to drop:
// if kept region is entirely in front
// then we drop front and back parts of front and all of back
// else if kept region is entirely in back
// then we drop front and back parts of back and all of front
// else kept region straddles the slice boundary,
// so we drop front part of front and back part of back
// (4) set head and len
// (5) drop regions via guards/drop_in_place
}
I'm sure that there will be bikeshedding about the name. I wanted the name to include "range" since it's the range that sets it apart from, e.g., a retain, and this isn't a retain since it has no predicate. The "to" should make clear that the range is what you'll be left with, not what you're removing. The "truncate" should serve to indicate that this operation is fast (if there is no drop code), as truncates of data structures or database tables are usually fast.
In discussion, truncate_both was brought up as a negative suggestion.
Alternatives
truncate + truncate_front + math
drain into a new VecDeque
make_contiguous and narrow the slice
as_slices and narrow the two slices
Links and related work
What happens now?
This issue contains an API change proposal (or ACP) and is part of the libs-api team feature lifecycle. Once this issue is filed, the libs-api team will review open proposals as capability becomes available. Current response times do not have a clear estimate, but may be up to several months.
Possible responses
The libs team may respond in various different ways. First, the team will consider the problem (this doesn't require any concrete solution or alternatives to have been proposed):
- We think this problem seems worth solving, and the standard library might be the right place to solve it.
- We think that this probably doesn't belong in the standard library.
Second, if there's a concrete solution:
- We think this specific solution looks roughly right, approved, you or someone else should implement this. (Further review will still happen on the subsequent implementation PR.)
- We're not sure this is the right solution, and the alternatives or other materials don't give us enough information to be sure about that. Here are some questions we have that aren't answered, or rough ideas about alternatives we'd want to see discussed.
Proposal
Problem statement
VecDequecurrently allows truncating down to a specific length via dropping elements from the front (truncate_front) or the back (truncate), but it lacks a way to specify a range that should be kept while truncating the rest (which might truncate both ends).Motivating examples or use cases
A system collects metrics during a period in which a benchmark is run, but collection inevitably starts before the load is applied and continues for some time after it ends. Let's clip off those pre- and post-test data points before analyzing the results.
Other ideas:
Solution sketch
I'm sure that there will be bikeshedding about the name. I wanted the name to include "range" since it's the range that sets it apart from, e.g., a
retain, and this isn't aretainsince it has no predicate. The "to" should make clear that the range is what you'll be left with, not what you're removing. The "truncate" should serve to indicate that this operation is fast (if there is no drop code), as truncates of data structures or database tables are usually fast.In discussion,
truncate_bothwas brought up as a negative suggestion.Alternatives
truncate+truncate_front+ mathdraininto a newVecDequemake_contiguousand narrow the sliceas_slicesand narrow the two slicesLinks and related work
What happens now?
This issue contains an API change proposal (or ACP) and is part of the libs-api team feature lifecycle. Once this issue is filed, the libs-api team will review open proposals as capability becomes available. Current response times do not have a clear estimate, but may be up to several months.
Possible responses
The libs team may respond in various different ways. First, the team will consider the problem (this doesn't require any concrete solution or alternatives to have been proposed):
Second, if there's a concrete solution: