From 4af76e88f3e40d44b06e58d14ba35c0f1114bcdd Mon Sep 17 00:00:00 2001 From: Clar Charr Date: Sun, 29 Jan 2017 13:35:40 -0500 Subject: [PATCH 1/2] Add Iterator::rfind. --- src/libcore/iter/iterator.rs | 58 ++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 3b406873d4b19..0d34e06193c8f 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -1488,6 +1488,64 @@ pub trait Iterator { None } + /// Searches for an element of an iterator from the right that satisfies a predicate. + /// + /// `rfind()` takes a closure that returns `true` or `false`. It applies + /// this closure to each element of the iterator, starting at the end, and if any + /// of them return `true`, then `rfind()` returns [`Some(element)`]. If they all return + /// `false`, it returns [`None`]. + /// + /// `rfind()` is short-circuiting; in other words, it will stop processing + /// as soon as the closure returns `true`. + /// + /// Because `rfind()` takes a reference, and many iterators iterate over + /// references, this leads to a possibly confusing situation where the + /// argument is a double reference. You can see this effect in the + /// examples below, with `&&x`. + /// + /// [`Some(element)`]: ../../std/option/enum.Option.html#variant.Some + /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(iter_rfind)] + /// + /// let a = [1, 2, 3]; + /// + /// assert_eq!(a.iter().rfind(|&&x| x == 2), Some(&2)); + /// + /// assert_eq!(a.iter().rfind(|&&x| x == 5), None); + /// ``` + /// + /// Stopping at the first `true`: + /// + /// ``` + /// #![feature(iter_rfind)] + /// + /// let a = [1, 2, 3]; + /// + /// let mut iter = a.iter(); + /// + /// assert_eq!(iter.rfind(|&&x| x == 2), Some(&2)); + /// + /// // we can still use `iter`, as there are more elements. + /// assert_eq!(iter.next_back(), Some(&1)); + /// ``` + #[inline] + #[unstable(feature = "iter_rfind", issue = "0")] + fn rfind

(&mut self, mut predicate: P) -> Option where + Self: Sized + DoubleEndedIterator, + P: FnMut(&Self::Item) -> bool + { + for x in self.by_ref().rev() { + if predicate(&x) { return Some(x) } + } + None + } + /// Searches for an element in an iterator, returning its index. /// /// `position()` takes a closure that returns `true` or `false`. It applies From 3cf485c96322085f0af162b2a1458bfca0423f3c Mon Sep 17 00:00:00 2001 From: Clar Charr Date: Thu, 2 Feb 2017 23:56:10 -0500 Subject: [PATCH 2/2] Move rfind to DoubleEndedIterator, add tracking issue. --- src/libcore/iter/iterator.rs | 58 ------------------------------------ src/libcore/iter/traits.rs | 58 ++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 58 deletions(-) diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 0d34e06193c8f..3b406873d4b19 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -1488,64 +1488,6 @@ pub trait Iterator { None } - /// Searches for an element of an iterator from the right that satisfies a predicate. - /// - /// `rfind()` takes a closure that returns `true` or `false`. It applies - /// this closure to each element of the iterator, starting at the end, and if any - /// of them return `true`, then `rfind()` returns [`Some(element)`]. If they all return - /// `false`, it returns [`None`]. - /// - /// `rfind()` is short-circuiting; in other words, it will stop processing - /// as soon as the closure returns `true`. - /// - /// Because `rfind()` takes a reference, and many iterators iterate over - /// references, this leads to a possibly confusing situation where the - /// argument is a double reference. You can see this effect in the - /// examples below, with `&&x`. - /// - /// [`Some(element)`]: ../../std/option/enum.Option.html#variant.Some - /// [`None`]: ../../std/option/enum.Option.html#variant.None - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// #![feature(iter_rfind)] - /// - /// let a = [1, 2, 3]; - /// - /// assert_eq!(a.iter().rfind(|&&x| x == 2), Some(&2)); - /// - /// assert_eq!(a.iter().rfind(|&&x| x == 5), None); - /// ``` - /// - /// Stopping at the first `true`: - /// - /// ``` - /// #![feature(iter_rfind)] - /// - /// let a = [1, 2, 3]; - /// - /// let mut iter = a.iter(); - /// - /// assert_eq!(iter.rfind(|&&x| x == 2), Some(&2)); - /// - /// // we can still use `iter`, as there are more elements. - /// assert_eq!(iter.next_back(), Some(&1)); - /// ``` - #[inline] - #[unstable(feature = "iter_rfind", issue = "0")] - fn rfind

(&mut self, mut predicate: P) -> Option where - Self: Sized + DoubleEndedIterator, - P: FnMut(&Self::Item) -> bool - { - for x in self.by_ref().rev() { - if predicate(&x) { return Some(x) } - } - None - } - /// Searches for an element in an iterator, returning its index. /// /// `position()` takes a closure that returns `true` or `false`. It applies diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index 1e12714830067..a86ceb9ac0d37 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -414,6 +414,64 @@ pub trait DoubleEndedIterator: Iterator { /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn next_back(&mut self) -> Option; + + /// Searches for an element of an iterator from the right that satisfies a predicate. + /// + /// `rfind()` takes a closure that returns `true` or `false`. It applies + /// this closure to each element of the iterator, starting at the end, and if any + /// of them return `true`, then `rfind()` returns [`Some(element)`]. If they all return + /// `false`, it returns [`None`]. + /// + /// `rfind()` is short-circuiting; in other words, it will stop processing + /// as soon as the closure returns `true`. + /// + /// Because `rfind()` takes a reference, and many iterators iterate over + /// references, this leads to a possibly confusing situation where the + /// argument is a double reference. You can see this effect in the + /// examples below, with `&&x`. + /// + /// [`Some(element)`]: ../../std/option/enum.Option.html#variant.Some + /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(iter_rfind)] + /// + /// let a = [1, 2, 3]; + /// + /// assert_eq!(a.iter().rfind(|&&x| x == 2), Some(&2)); + /// + /// assert_eq!(a.iter().rfind(|&&x| x == 5), None); + /// ``` + /// + /// Stopping at the first `true`: + /// + /// ``` + /// #![feature(iter_rfind)] + /// + /// let a = [1, 2, 3]; + /// + /// let mut iter = a.iter(); + /// + /// assert_eq!(iter.rfind(|&&x| x == 2), Some(&2)); + /// + /// // we can still use `iter`, as there are more elements. + /// assert_eq!(iter.next_back(), Some(&1)); + /// ``` + #[inline] + #[unstable(feature = "iter_rfind", issue = "39480")] + fn rfind

(&mut self, mut predicate: P) -> Option where + Self: Sized, + P: FnMut(&Self::Item) -> bool + { + for x in self.by_ref().rev() { + if predicate(&x) { return Some(x) } + } + None + } } #[stable(feature = "rust1", since = "1.0.0")]