Skip to content

Commit

Permalink
Add find_result at Iterator
Browse files Browse the repository at this point in the history
  • Loading branch information
MOZGIII committed Jul 31, 2019
1 parent e3976ff commit 017f987
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 0 deletions.
36 changes: 36 additions & 0 deletions src/libcore/iter/traits/iterator.rs
Expand Up @@ -1963,6 +1963,42 @@ pub trait Iterator {
}).break_value()
}

/// Applies function to the elements of iterator and returns
/// the first non-none result or the first error.
///
///
/// # Examples
///
/// ```
/// let a = ["1", "2", "lol", "NaN", "5"];
///
/// let result = a.iter().find_result(|&s| s.parse()? == 2);
///
/// assert_eq!(result, Ok(Some(&2)));
/// ```
///
/// ```
/// let a = ["1", "2", "lol", "NaN", "5"];
///
/// let result = a.iter().find_result(|&s| s.parse()? == 5);
///
/// assert!(result.is_err());
/// ```
#[inline]
#[unstable(feature = "find_result", reason = "new API", issue = "?")]
fn find_result<F, E>(&mut self, mut f: F) -> Result<Option<Self::Item>, E> where
Self: Sized,
F: FnMut(&Self::Item) -> Result<bool, E>,
{
self.try_for_each(move |x| {
match f(&x) {
Ok(false) => LoopState::Continue(()),
Ok(true) => LoopState::Break(Ok(x)),
Err(x) => LoopState::Break(Err(x)),
}
}).break_value().transpose()
}

/// Searches for an element in an iterator, returning its index.
///
/// `position()` takes a closure that returns `true` or `false`. It applies
Expand Down
26 changes: 26 additions & 0 deletions src/libcore/tests/iter.rs
Expand Up @@ -1258,6 +1258,32 @@ fn test_find_map() {
}
}

#[test]
fn test_find_result() {
let xs: &[isize] = &[];
assert_eq!(xs.iter().find_result(testfn), Ok(None));
let xs: &[isize] = &[1, 2, 3, 4];
assert_eq!(xs.iter().find_result(testfn), Ok(Some(&2)));
let xs: &[isize] = &[1, 3, 4];
assert_eq!(xs.iter().find_result(testfn), Err(()));

let xs: &[isize] = &[1, 2, 3, 4, 5, 6, 7];
let mut iter = xs.iter();
assert_eq!(iter.find_result(testfn), Ok(Some(&2)));
assert_eq!(iter.find_result(testfn), Err(()));
assert_eq!(iter.next(), Some(&5));

fn testfn(x: &&isize) -> Result<bool, ()> {
if **x == 2 {
return Ok(true);
}
if **x == 4 {
return Err(());
}
Ok(false)
}
}

#[test]
fn test_position() {
let v = &[1, 3, 9, 27, 103, 14, 11];
Expand Down

0 comments on commit 017f987

Please sign in to comment.