Skip to content

Commit

Permalink
Auto merge of #60396 - cuviper:ordered-retain, r=scottmcm
Browse files Browse the repository at this point in the history
Document the order of {Vec,VecDeque,String}::retain

It's natural for `retain` to work in order from beginning to end, but
this wasn't actually documented to be the case. If we actually promise
this, then the caller can do useful things like track the index of each
element being tested, as [discussed in the forum][1]. This is now
documented for `Vec`, `VecDeque`, and `String`.

[1]: https://users.rust-lang.org/t/vec-retain-by-index/27697

`HashMap` and `HashSet` also have `retain`, and the `hashbrown`
implementation does happen to use a plain `iter()` order too, but it's
not certain that this should always be the case for these types.

r? @scottmcm
  • Loading branch information
bors committed May 12, 2019
2 parents d28e948 + 0545375 commit 16e356e
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 6 deletions.
18 changes: 16 additions & 2 deletions src/liballoc/collections/vec_deque.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1835,8 +1835,8 @@ impl<T> VecDeque<T> {
/// Retains only the elements specified by the predicate.
///
/// In other words, remove all elements `e` such that `f(&e)` returns false.
/// This method operates in place and preserves the order of the retained
/// elements.
/// This method operates in place, visiting each element exactly once in the
/// original order, and preserves the order of the retained elements.
///
/// # Examples
///
Expand All @@ -1848,6 +1848,20 @@ impl<T> VecDeque<T> {
/// buf.retain(|&x| x%2 == 0);
/// assert_eq!(buf, [2, 4]);
/// ```
///
/// The exact order may be useful for tracking external state, like an index.
///
/// ```
/// use std::collections::VecDeque;
///
/// let mut buf = VecDeque::new();
/// buf.extend(1..6);
///
/// let keep = [false, true, true, false, true];
/// let mut i = 0;
/// buf.retain(|_| (keep[i], i += 1).0);
/// assert_eq!(buf, [2, 3, 5]);
/// ```
#[stable(feature = "vec_deque_retain", since = "1.4.0")]
pub fn retain<F>(&mut self, mut f: F)
where F: FnMut(&T) -> bool
Expand Down
14 changes: 12 additions & 2 deletions src/liballoc/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1200,8 +1200,8 @@ impl String {
/// Retains only the characters specified by the predicate.
///
/// In other words, remove all characters `c` such that `f(c)` returns `false`.
/// This method operates in place and preserves the order of the retained
/// characters.
/// This method operates in place, visiting each character exactly once in the
/// original order, and preserves the order of the retained characters.
///
/// # Examples
///
Expand All @@ -1212,6 +1212,16 @@ impl String {
///
/// assert_eq!(s, "foobar");
/// ```
///
/// The exact order may be useful for tracking external state, like an index.
///
/// ```
/// let mut s = String::from("abcde");
/// let keep = [false, true, true, false, true];
/// let mut i = 0;
/// s.retain(|_| (keep[i], i += 1).0);
/// assert_eq!(s, "bce");
/// ```
#[inline]
#[stable(feature = "string_retain", since = "1.26.0")]
pub fn retain<F>(&mut self, mut f: F)
Expand Down
14 changes: 12 additions & 2 deletions src/liballoc/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -937,8 +937,8 @@ impl<T> Vec<T> {
/// Retains only the elements specified by the predicate.
///
/// In other words, remove all elements `e` such that `f(&e)` returns `false`.
/// This method operates in place and preserves the order of the retained
/// elements.
/// This method operates in place, visiting each element exactly once in the
/// original order, and preserves the order of the retained elements.
///
/// # Examples
///
Expand All @@ -947,6 +947,16 @@ impl<T> Vec<T> {
/// vec.retain(|&x| x%2 == 0);
/// assert_eq!(vec, [2, 4]);
/// ```
///
/// The exact order may be useful for tracking external state, like an index.
///
/// ```
/// let mut vec = vec![1, 2, 3, 4, 5];
/// let keep = [false, true, true, false, true];
/// let mut i = 0;
/// vec.retain(|_| (keep[i], i += 1).0);
/// assert_eq!(vec, [2, 3, 5]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn retain<F>(&mut self, mut f: F)
where F: FnMut(&T) -> bool
Expand Down

0 comments on commit 16e356e

Please sign in to comment.