Skip to content

Commit d70b98e

Browse files
committed
RFC to add retain_mut to Vec and VecDeque
1 parent ffe3f8b commit d70b98e

File tree

1 file changed

+66
-0
lines changed

1 file changed

+66
-0
lines changed

text/0000-vec-retain_mut.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
- Feature Name: retain_mut
2+
- Start Date: 2015-11-6
3+
- RFC PR: (leave this empty)
4+
- Rust Issue: (leave this empty)
5+
6+
# Summary
7+
[summary]: #summary
8+
9+
Add a `retain_mut` method to `Vec` and `VecDeque` which allows elements to be
10+
mutated before deciding whether to retain them.
11+
12+
# Motivation
13+
[motivation]: #motivation
14+
15+
A common pattern with vectors is to look at each element, modify it and
16+
remove it from the vector if a certain condition is met. The `retain` method
17+
allows elements to be removed from a vector in-place but does not allow existing
18+
elements to be modified.
19+
20+
The lack of a `retain_mut` method means that users have to do 2 passes, one with
21+
`iter_mut` and one with `retain`. The resulting code is harder to read and
22+
slower. Another, more efficient, way of doing this would be to work with vector
23+
indices directly and swap elements into place while mutating them, similar to
24+
what `retain` already does.
25+
26+
# Detailed design
27+
[design]: #detailed-design
28+
29+
The only difference between `retain_mut` and `retain` is that `retain_mut` takes
30+
a `FnMut(&mut T)` parameter instead of a `FnMut(&T)`. This allows elements to
31+
be mutated before deciding whether to retain them.
32+
33+
The new `retain_mut` method will be added to both `Vec` and `VecDeque`.
34+
35+
Here is an example which will decrement each element of a vector and filter out
36+
elements that have reached a value of zero.
37+
38+
let mut vec = vec![7, 1, 3, 10];
39+
vec.retain_mut(|x| {
40+
*x -= 1;
41+
*x != 0
42+
});
43+
assert_eq!(vec, [6, 2, 9]);
44+
45+
# Drawbacks
46+
[drawbacks]: #drawbacks
47+
48+
The `retain` method really should have had a `FnMut(&mut T)` parameter from the
49+
start, but it is too late to change that. Adding `retain_mut` will result in
50+
two methods that have almost identical implementations.
51+
52+
# Alternatives
53+
[alternatives]: #alternatives
54+
55+
Changing the existing `retain` method to take a `FnMut(&mut T)` was considered
56+
in rust-lang/rust#25477 but this is likely to break a lot of existing code which
57+
passes a closure defined using `|&x| {...}`.
58+
59+
Another alternative is to not do anything. Users can implement their own version
60+
of `retain_mut` or they can restructure their code into an `iter_mut` pass on
61+
the vector followed by a `retain` pass.
62+
63+
# Unresolved questions
64+
[unresolved]: #unresolved-questions
65+
66+
None

0 commit comments

Comments
 (0)