Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upTracking issue for Vec::drain_filter and LinkedList::drain_filter #43244
Comments
Mark-Simulacrum
added
B-unstable
T-libs
C-tracking-issue
labels
Jul 19, 2017
This comment has been minimized.
This comment has been minimized.
bors
added a commit
that referenced
this issue
Aug 15, 2017
This comment has been minimized.
This comment has been minimized.
|
Maybe this doesn't need to include the kitchen sink, but it could have a range parameter, so that it's like a superset of drain. Any drawbacks to that? I guess adding bounds checking for the range is a drawback, it's another thing that can panic. But drain_filter(.., f) can not. |
This comment has been minimized.
This comment has been minimized.
rustonaut
commented
Sep 11, 2017
•
|
Is there any chance this will stabilize in some form in the not to far future? |
This comment has been minimized.
This comment has been minimized.
rustonaut
commented
Sep 11, 2017
•
|
If the compiler is clever enough to eliminate the bounds checks ( And I'm pretty sure you can implement it in a way |
This comment has been minimized.
This comment has been minimized.
|
I know this is bikeshedding to some extent, but what was the reasoning behind naming this |
This comment has been minimized.
This comment has been minimized.
rustonaut
commented
Sep 23, 2017
|
No idea, but |
This comment has been minimized.
This comment has been minimized.
|
|
This comment has been minimized.
This comment has been minimized.
rustonaut
commented
Sep 23, 2017
•
|
I think
|
This comment has been minimized.
This comment has been minimized.
|
There is no precedent for using |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
The "said equivalent" code in the comment is not correct... you have to minus one from i at the "your code here" site, or bad things happens. |
This comment has been minimized.
This comment has been minimized.
thegranddesign
commented
Oct 25, 2017
|
IMO it's not Again, just from a newbie perspective, the things I would search for if trying to find something to do what this issue proposes would be I actually searched for It seems like a simple function named |
This comment has been minimized.
This comment has been minimized.
thegranddesign
commented
Oct 25, 2017
|
On a separate note, I don't feel as though this should mutate the vector it's called on. It prevents chaining. In an ideal scenario one would want to be able to do something like: vec![
"",
"something",
a_variable,
function_call(),
"etc",
]
.reject(|i| { i.is_empty() })
.join("/")With the current implementation, what it would be joining on would be the rejected values. I'd like to see both an |
This comment has been minimized.
This comment has been minimized.
|
You can already do the chaining thing with |
This comment has been minimized.
This comment has been minimized.
thegranddesign
commented
Oct 25, 2017
This comment has been minimized.
This comment has been minimized.
|
Yes, it's a member of |
This comment has been minimized.
This comment has been minimized.
|
Drain is novel terminology because it represented a fourth kind of ownership in Rust that only applies to containers, while also generally being a meaningless distinction in almost any other language (in the absence of move semantics, there is no need to combine iteration and removal into a single ""atomic"" operation). Although drain_filter moves the drain terminology into a space that other languages would care about (since avoiding backshifts is relevant in all languages). |
kennytm
changed the title
Tracking issue for Vec::drain_filter
Tracking issue for Vec::drain_filter and LinkedList::drain_filter
Nov 27, 2017
This comment has been minimized.
This comment has been minimized.
polarathene
commented
Dec 3, 2017
|
I came across
|
This comment has been minimized.
This comment has been minimized.
|
I still feel as though |
This comment has been minimized.
This comment has been minimized.
|
Shouldn't |
This comment has been minimized.
This comment has been minimized.
|
Yes |
bors
added a commit
that referenced
this issue
Dec 9, 2017
bors
added a commit
that referenced
this issue
Dec 9, 2017
This comment has been minimized.
This comment has been minimized.
How and where does the team foresee this type of experimentation happening? |
This comment has been minimized.
This comment has been minimized.
|
How: come up with and propose a concrete API design, possibly with a proof-of-concept implementation (which can be done out of tree through at least |
This comment has been minimized.
This comment has been minimized.
|
I've been playing around with this for a bit. I'll open a thread on internals in the next days. |
This comment has been minimized.
This comment has been minimized.
Boscop
commented
Apr 25, 2018
|
I think a general API that works like this makes sense: v.drain(a..b).where(pred)So it's a builder-style API: If If the name The v.drain(..).where(pred1).filter(pred2)Here, it will use What do you think about this kind of builder-style API approach? |
This comment has been minimized.
This comment has been minimized.
Boscop
commented
Apr 25, 2018
|
For a second I forgot that And Then I think the second best overall option is to keep the current (As jonhoo said above: )
|
This comment has been minimized.
This comment has been minimized.
|
I've opened a thread on internals. Edit: I've uploaded my experimental code: drain experiments |
This comment has been minimized.
This comment has been minimized.
Popog
commented
May 11, 2018
|
Totally missed out on this thread. I've had an old impl that I've fixed up a bit and copy pasted to reflect a few of the options described in this thread. The one nice thing about the impl that I think will be non-controversial is that it implements |
This comment has been minimized.
This comment has been minimized.
Boscop
commented
May 11, 2018
|
@Emerentius but then we should at least rename |
This comment has been minimized.
This comment has been minimized.
|
@Boscop Both imply the same 'polarity' of @Popog Can you summarize the differences and pros & cons? Ideally over at the internals thread. I think |
This comment has been minimized.
This comment has been minimized.
askeksa
commented
May 26, 2018
|
How about |
This comment has been minimized.
This comment has been minimized.
Boscop
commented
Jun 2, 2018
|
@askeksa But that doesn't make it clear whether returning |
This comment has been minimized.
This comment has been minimized.
|
It would be nice if there was some way to limit/stop/cancel/abort the drain. For example, if I wanted to drain the first N even numbers, it would be nice to be able to just do As it's currently implemented, |
This comment has been minimized.
This comment has been minimized.
|
If you want that behaviour you should just close over some state that tracks how many you've seen and start returning false. Running to completion on drop is necessary to make adaptors behave reasonably. |
This comment has been minimized.
This comment has been minimized.
rustonaut
commented
Jun 12, 2018
|
I just noticed that the way I know that
An example of this behaviour is here: |
This comment has been minimized.
This comment has been minimized.
rustonaut
commented
Jun 12, 2018
•
|
While the 2. point should be solvable I think the first point on itself should
Arguments for running to completion include:
It might be just me or I missed some point but changing the If |
This comment has been minimized.
This comment has been minimized.
I can't find the original reasoning, but I remember there was also some problem with adapters working with a See also #43244 (comment) |
This comment has been minimized.
This comment has been minimized.
rustonaut
commented
Jun 12, 2018
|
Good point, e.g. Hm, maybe I should change my opinion. Through this might be a general problem |
This comment has been minimized.
This comment has been minimized.
|
I have personally not found any safety reason why drain needs to run to completion but as I've written here a couple posts above, the side-effects on This also brings up the same issues as my RFC on non-selfexhausting drain and its companion selfexhausting iter adapter RFC. It's true that |
This comment has been minimized.
This comment has been minimized.
rustonaut
commented
Jun 12, 2018
•
|
Yup, I already did: play.rust-lang.org Which is this: #![feature(drain_filter)]
use std::panic::catch_unwind;
struct PrintOnDrop {
id: u8
}
impl Drop for PrintOnDrop {
fn drop(&mut self) {
println!("dropped: {}", self.id)
}
}
fn main() {
println!("-- start --");
let _ = catch_unwind(move || {
let mut a: Vec<_> = [0, 1, 4, 5, 6].iter()
.map(|&id| PrintOnDrop { id })
.collect::<Vec<_>>();
let drain = a.drain_filter(|dc| {
if dc.id == 4 { panic!("let's say a unwrap went wrong"); }
dc.id < 4
});
drain.for_each(::std::mem::drop);
});
println!("-- end --");
//output:
// -- start --
// dropped: 0 <-\
// dropped: 1 \_ this is a double drop
// dropped: 0 _ <-/
// dropped: 5 \------ here 4 got leaked (kind fine)
// dropped: 6
// -- end --
}But that's an implementation internal think, which went wrong.
Another question is if it's a good idea to run functions which can be seen as api user input on drop Maybe a consideration could be something like:
Maybe there is an better solution. |
This comment has been minimized.
This comment has been minimized.
|
@dathinab
Leaking is undesirable but fine and may be hard to avoid here, but a double-drop is definitely not. Good catch! Would you like to report a separate issue about this safety problem? |
This comment has been minimized.
This comment has been minimized.
vityafx
commented
Aug 10, 2018
•
|
Does Also, why there is no |
This comment has been minimized.
This comment has been minimized.
rustonaut
commented
Aug 10, 2018
|
The last time I took a at the code it did something like: created a "gap"
when moving out elements and move a element which is not drained to the
begin of the gap when it finds one. With this each element which has to be
moved (either out or to a new place in the array) is only moved once.
Also like e.g. `remove` it doesn't reallocate. The freed part just becomes
part of the unused capacity.
…On Fri, Aug 10, 2018, 07:11 Victor Polevoy ***@***.***> wrote:
Does drain_filter do reallocations every time it removes an item from
collection? Or it does reallocation only once and works like std::remove
and std::erase (in pair) in C++? I'd prefer such behavior because of
exactly one allocation: we simply put our elements to the end of collection
and then removes shrink it to proper size.
Also, why there is no try_drain_filter ? Which returns Option type, and
None value if we should stop? I have a very big collection and it is
meaningless to continue for me when I have already got what I needed.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#43244 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AHR0kdOZm4bj6iR9Hj831Qh72d36BxQSks5uPRYNgaJpZM4OY1me>
.
|
This comment has been minimized.
This comment has been minimized.
vityafx
commented
Aug 10, 2018
•
|
@rustonaut thanks. What is your opinion about P.S. Just looked at the code too, it looks as it works the way we wanted. |
This comment has been minimized.
This comment has been minimized.
rustonaut
commented
Aug 10, 2018
|
It advances element by element when iteration, so normally you could expect
it to stop iterating when being dropped, but it was deemed to be too
confusing so it actually drains to the end when dropped.
(Which drastically increases the likely hood of double panics and stuff
like that).
So it's unlikely that you will get a try version which behaves like you
expect.
For fairness drain early stopping when iterating really can be confusing in
some situations e.g. `thing.drain_where(|x| x.is_malformed()).any(|x|
x.is_dangerus())` would not drain all malformed ones but just until one of
found which is also dangerous. (The current Impl. does drain all malformed
by continuing draining on drop).
…On Fri, Aug 10, 2018, 10:52 Victor Polevoy ***@***.***> wrote:
@rustonaut <https://github.com/rustonaut> thanks. What is your opinion
about try_drain_filter? :)
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#43244 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AHR0kcEMHCayqvhI6D4LK4ITG2x5di-9ks5uPUnpgaJpZM4OY1me>
.
|
This comment has been minimized.
This comment has been minimized.
|
I think this would be more versatile: fn drain_filter_map<F>(&mut self, f: F) -> DrainFilterMap<T, F> where F: FnMut(T) -> Option<T> |
This comment has been minimized.
This comment has been minimized.
azriel91
commented
Feb 12, 2019
|
Hi, I was searching for the |
Ralith
referenced this issue
Mar 30, 2019
Merged
Keep buffered connections alive and shut down endpoint when dead #273
This comment has been minimized.
This comment has been minimized.
|
Is anything currently blocking this from stabilization? Is it still unwind-unsafe as reported above? This seems like a pretty small feature, and it has been in limbo for over a year. |
Gankro commentedJul 14, 2017
I'm sure there's an issue for this somewhere, but I can't find it. Someone nerd sniped me into implementing it. PR incoming.