Open
Description
Feature gate: #![feature(drain_keep_rest)]
This is a tracking issue for vec::Drain{,Filter}::keep_rest
, methods allowing to keep elements in a Vec
after draining some of them.
Public API
// mod alloc::vec
impl<T, A: Allocator> Drain<'_, T, A> {
pub fn keep_rest(self);
}
impl<T, F, A: Allocator> DrainFilter<'_, T, F, A>
where
F: FnMut(&mut T) -> bool,
{
pub fn keep_rest(self);
}
Steps / History
- Implementation: Add
vec::Drain{,Filter}::keep_rest
#95376 - Final comment period (FCP)1
- Stabilization PR
Unresolved Questions
- Just change the not-yet-stable Drop for DrainFilter to keep rest?
- Advantage: usually what you want (??)
- e.g.
.drain_filter(f).take(N)
works as expected
- e.g.
- Disadvantage: inconsistent with stable
Drop
forDrain
- If you want to remove rest (matching the current unstable behavior of
drain_filter
) then you'd need to write.foreach(drop)
to explicitly drop all the rest of the range that matches the filter.
- Advantage: usually what you want (??)
&mut self
instead ofself
?- If you're holding a
Drain
inside a struct and are operating on it from a&mut self
method of the struct,keep_rest(self)
is impossible to use. :(- You'd want something like
mem::replace(&mut self.drain_filter, Vec::new().drain(..)).keep_rest()
but the borrow checker won't like that. - Failing that, you'd need to change your
Drain
field toOption<Drain>
and useself.drain_filter.take().unwrap().keep_rest()
along withunwrap()
everywhere else that the drain is used. Not good.
- You'd want something like
- We'd need to define behavior of calling .next() after .keep_rest(). Presumably one of:
.next()
returnsNone
- this is considered incorrect usage and so
.next()
panic!
s .keep_rest()
sets a flag inside theDrain
whichDrop
will use to decide its behavior, and you're free to continue accessing iterator elements in between.
- Another alternative: add a
const EXHAUST_ON_DROP: bool = true
const generic parameter- It's still impossible to set the flag without ownership
- You can store
&mut Drain<'a, T, A, false>
from the beginning - Works better with iterator APIs, i.e.
Instead of
vec.drain_filter(f).keeping_rest().take(N).for_each(g);
let mut iter = vec.drain_filter(f); iter.by_ref().take(N).for_each(g); iter.keep_rest()
- If you're holding a
Footnotes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment