diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs
index 31f77f92435d..f039d1730eb3 100644
--- a/src/libcore/iter/iterator.rs
+++ b/src/libcore/iter/iterator.rs
@@ -1745,6 +1745,38 @@ fn find
(&mut self, mut predicate: P) -> Option where
}).break_value()
}
+ /// Applies function to the elements of iterator and returns
+ /// the first non-none result.
+ ///
+ /// `iter.find_map(f)` is equivalent to `iter.filter_map(f).next()`.
+ ///
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(iterator_find_map)]
+ /// let a = ["lol", "NaN", "2", "5"];
+ ///
+ /// let mut first_number = a.iter().find_map(|s| s.parse().ok());
+ ///
+ /// assert_eq!(first_number, Some(2));
+ /// ```
+ #[inline]
+ #[unstable(feature = "iterator_find_map",
+ reason = "unstable new API",
+ issue = "49602")]
+ fn find_map(&mut self, mut f: F) -> Option where
+ Self: Sized,
+ F: FnMut(Self::Item) -> Option,
+ {
+ self.try_for_each(move |x| {
+ match f(x) {
+ Some(x) => LoopState::Break(x),
+ None => LoopState::Continue(()),
+ }
+ }).break_value()
+ }
+
/// 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/tests/iter.rs b/src/libcore/tests/iter.rs
index a962efadd64e..2abac0cf1d5b 100644
--- a/src/libcore/tests/iter.rs
+++ b/src/libcore/tests/iter.rs
@@ -1146,6 +1146,33 @@ fn test_find() {
assert!(v.iter().find(|&&x| x % 12 == 0).is_none());
}
+#[test]
+fn test_find_map() {
+ let xs: &[isize] = &[];
+ assert_eq!(xs.iter().find_map(half_if_even), None);
+ let xs: &[isize] = &[3, 5];
+ assert_eq!(xs.iter().find_map(half_if_even), None);
+ let xs: &[isize] = &[4, 5];
+ assert_eq!(xs.iter().find_map(half_if_even), Some(2));
+ let xs: &[isize] = &[3, 6];
+ assert_eq!(xs.iter().find_map(half_if_even), Some(3));
+
+ let xs: &[isize] = &[1, 2, 3, 4, 5, 6, 7];
+ let mut iter = xs.iter();
+ assert_eq!(iter.find_map(half_if_even), Some(1));
+ assert_eq!(iter.find_map(half_if_even), Some(2));
+ assert_eq!(iter.find_map(half_if_even), Some(3));
+ assert_eq!(iter.next(), Some(&7));
+
+ fn half_if_even(x: &isize) -> Option {
+ if x % 2 == 0 {
+ Some(x / 2)
+ } else {
+ None
+ }
+ }
+}
+
#[test]
fn test_position() {
let v = &[1, 3, 9, 27, 103, 14, 11];
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index 1a68f04532d2..6f6105553d4d 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -48,6 +48,7 @@
#![feature(atomic_nand)]
#![feature(reverse_bits)]
#![feature(inclusive_range_fields)]
+#![feature(iterator_find_map)]
extern crate core;
extern crate test;