Add Iterator::try_find
This commit is contained in:
parent
38aa6bdfd7
commit
5446cc99bb
@ -2104,6 +2104,43 @@ fn check<T, B>(mut f: impl FnMut(T) -> Option<B>) -> impl FnMut((), T) -> LoopSt
|
||||
self.try_fold((), check(f)).break_value()
|
||||
}
|
||||
|
||||
/// Applies function to the elements of iterator and returns
|
||||
/// the first non-none result or the first error.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(try_find)]
|
||||
///
|
||||
/// let a = ["1", "2", "lol", "NaN", "5"];
|
||||
///
|
||||
/// let is_my_num = |s: &str, search: i32| -> Result<bool, std::num::ParseIntError> {
|
||||
/// Ok(s.parse::<i32>()? == search)
|
||||
/// };
|
||||
///
|
||||
/// let result = a.iter().try_find(|&&s| is_my_num(s, 2));
|
||||
/// assert_eq!(result, Ok(Some(&"2")));
|
||||
///
|
||||
/// let result = a.iter().try_find(|&&s| is_my_num(s, 5));
|
||||
/// assert!(result.is_err());
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "try_find", reason = "new API", issue = "63178")]
|
||||
fn try_find<F, E, R>(&mut self, mut f: F) -> Result<Option<Self::Item>, E>
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(&Self::Item) -> R,
|
||||
R: Try<Ok = bool, Error = E>,
|
||||
{
|
||||
self.try_for_each(move |x| match f(&x).into_result() {
|
||||
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
|
||||
|
@ -85,6 +85,7 @@
|
||||
#![feature(extern_types)]
|
||||
#![feature(fundamental)]
|
||||
#![feature(intrinsics)]
|
||||
#![feature(try_find)]
|
||||
#![feature(is_sorted)]
|
||||
#![feature(iter_once_with)]
|
||||
#![feature(lang_items)]
|
||||
|
@ -1557,6 +1557,46 @@ fn half_if_even(x: &isize) -> Option<isize> {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_find() {
|
||||
let xs: &[isize] = &[];
|
||||
assert_eq!(xs.iter().try_find(testfn), Ok(None));
|
||||
let xs: &[isize] = &[1, 2, 3, 4];
|
||||
assert_eq!(xs.iter().try_find(testfn), Ok(Some(&2)));
|
||||
let xs: &[isize] = &[1, 3, 4];
|
||||
assert_eq!(xs.iter().try_find(testfn), Err(()));
|
||||
|
||||
let xs: &[isize] = &[1, 2, 3, 4, 5, 6, 7];
|
||||
let mut iter = xs.iter();
|
||||
assert_eq!(iter.try_find(testfn), Ok(Some(&2)));
|
||||
assert_eq!(iter.try_find(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_try_find_api_usability() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let a = ["1", "2"];
|
||||
|
||||
let is_my_num = |s: &str, search: i32| -> Result<bool, std::num::ParseIntError> {
|
||||
Ok(s.parse::<i32>()? == search)
|
||||
};
|
||||
|
||||
let val = a.iter().try_find(|&&s| is_my_num(s, 2))?;
|
||||
assert_eq!(val, Some(&"2"));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_position() {
|
||||
let v = &[1, 3, 9, 27, 103, 14, 11];
|
||||
|
@ -11,6 +11,7 @@
|
||||
#![feature(flt2dec)]
|
||||
#![feature(fmt_internals)]
|
||||
#![feature(hashmap_internals)]
|
||||
#![feature(try_find)]
|
||||
#![feature(is_sorted)]
|
||||
#![feature(iter_once_with)]
|
||||
#![feature(pattern)]
|
||||
|
Loading…
Reference in New Issue
Block a user