mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-27 17:24:06 +00:00
Add a try_reduce
method to the Iterator trait
This commit is contained in:
parent
ff2439b7b9
commit
aef59e4fb8
@ -2216,6 +2216,86 @@ pub trait Iterator {
|
|||||||
Some(self.fold(first, f))
|
Some(self.fold(first, f))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reduces the elements to a single one by repeatedly applying a reducing operation. If the
|
||||||
|
/// closure returns a failure, the failure is propagated back to the caller immediately.
|
||||||
|
///
|
||||||
|
/// The return type of this method depends on the return type of the closure. If the closure
|
||||||
|
/// returns `Result<Self::Item, E>`, then this function will return `Result<Option<Self::Item>,
|
||||||
|
/// E>`. If the closure returns `Option<Self::Item>`, then this function will return
|
||||||
|
/// `Option<Option<Self::Item>>`.
|
||||||
|
///
|
||||||
|
/// When called on an empty iterator, this function will return either `Some(None)` or
|
||||||
|
/// `Ok(None)` depending on the type of the provided closure.
|
||||||
|
///
|
||||||
|
/// For iterators with at least one element, this is essentially the same as calling
|
||||||
|
/// [`try_fold()`] with the first element of the iterator as the initial accumulator value.
|
||||||
|
///
|
||||||
|
/// [`try_fold()`]: Iterator::try_fold
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// Safely calculate the sum of a series of numbers:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(iterator_try_reduce)]
|
||||||
|
///
|
||||||
|
/// let numbers: Vec<usize> = vec![10, 20, 5, 23, 0];
|
||||||
|
/// let sum = numbers.into_iter().try_reduce(|x, y| x.checked_add(y));
|
||||||
|
/// assert_eq!(sum, Some(Some(58)));
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Determine when a reduction short circuited:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(iterator_try_reduce)]
|
||||||
|
///
|
||||||
|
/// let numbers = vec![1, 2, 3, usize::MAX, 4, 5];
|
||||||
|
/// let sum = numbers.into_iter().try_reduce(|x, y| x.checked_add(y));
|
||||||
|
/// assert_eq!(sum, None);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Determine when a reduction was not performed because there are no elements:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(iterator_try_reduce)]
|
||||||
|
///
|
||||||
|
/// let numbers: Vec<usize> = Vec::new();
|
||||||
|
/// let sum = numbers.into_iter().try_reduce(|x, y| x.checked_add(y));
|
||||||
|
/// assert_eq!(sum, Some(None));
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Use a [`Result`] instead of an [`Option`]:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(iterator_try_reduce)]
|
||||||
|
///
|
||||||
|
/// let numbers = vec!["1", "2", "3", "4", "5"];
|
||||||
|
/// let max: Result<Option<_>, <usize as std::str::FromStr>::Err> =
|
||||||
|
/// numbers.into_iter().try_reduce(|x, y| {
|
||||||
|
/// if x.parse::<usize>()? > y.parse::<usize>()? { Ok(x) } else { Ok(y) }
|
||||||
|
/// });
|
||||||
|
/// assert_eq!(max, Ok(Some("5")));
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
#[unstable(feature = "iterator_try_reduce", reason = "new API", issue = "87053")]
|
||||||
|
fn try_reduce<F, R>(&mut self, f: F) -> ChangeOutputType<R, Option<R::Output>>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
F: FnMut(Self::Item, Self::Item) -> R,
|
||||||
|
R: Try<Output = Self::Item>,
|
||||||
|
R::Residual: Residual<Option<Self::Item>>,
|
||||||
|
{
|
||||||
|
let first = match self.next() {
|
||||||
|
Some(i) => i,
|
||||||
|
None => return Try::from_output(None),
|
||||||
|
};
|
||||||
|
|
||||||
|
match self.try_fold(first, f).branch() {
|
||||||
|
ControlFlow::Break(r) => FromResidual::from_residual(r),
|
||||||
|
ControlFlow::Continue(i) => Try::from_output(Some(i)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Tests if every element of the iterator matches a predicate.
|
/// Tests if every element of the iterator matches a predicate.
|
||||||
///
|
///
|
||||||
/// `all()` takes a closure that returns `true` or `false`. It applies
|
/// `all()` takes a closure that returns `true` or `false`. It applies
|
||||||
|
@ -454,6 +454,34 @@ fn test_find_map() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_try_reduce() {
|
||||||
|
let v: Vec<usize> = vec![1, 2, 3, 4, 5];
|
||||||
|
let sum = v.into_iter().try_reduce(|x, y| x.checked_add(y));
|
||||||
|
assert_eq!(sum, Some(Some(15)));
|
||||||
|
|
||||||
|
let v: Vec<usize> = vec![1, 2, 3, 4, 5, usize::MAX];
|
||||||
|
let sum = v.into_iter().try_reduce(|x, y| x.checked_add(y));
|
||||||
|
assert_eq!(sum, None);
|
||||||
|
|
||||||
|
let v: Vec<usize> = Vec::new();
|
||||||
|
let sum = v.into_iter().try_reduce(|x, y| x.checked_add(y));
|
||||||
|
assert_eq!(sum, Some(None));
|
||||||
|
|
||||||
|
let v = vec!["1", "2", "3", "4", "5"];
|
||||||
|
let max = v.into_iter().try_reduce(|x, y| {
|
||||||
|
if x.parse::<usize>().ok()? > y.parse::<usize>().ok()? { Some(x) } else { Some(y) }
|
||||||
|
});
|
||||||
|
assert_eq!(max, Some(Some("5")));
|
||||||
|
|
||||||
|
let v = vec!["1", "2", "3", "4", "5"];
|
||||||
|
let max: Result<Option<_>, <usize as std::str::FromStr>::Err> =
|
||||||
|
v.into_iter().try_reduce(|x, y| {
|
||||||
|
if x.parse::<usize>()? > y.parse::<usize>()? { Ok(x) } else { Ok(y) }
|
||||||
|
});
|
||||||
|
assert_eq!(max, Ok(Some("5")));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_iterator_len() {
|
fn test_iterator_len() {
|
||||||
let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||||
|
@ -56,6 +56,7 @@
|
|||||||
#![feature(iter_intersperse)]
|
#![feature(iter_intersperse)]
|
||||||
#![feature(iter_is_partitioned)]
|
#![feature(iter_is_partitioned)]
|
||||||
#![feature(iter_order_by)]
|
#![feature(iter_order_by)]
|
||||||
|
#![feature(iterator_try_reduce)]
|
||||||
#![feature(const_mut_refs)]
|
#![feature(const_mut_refs)]
|
||||||
#![feature(const_pin)]
|
#![feature(const_pin)]
|
||||||
#![feature(const_slice_from_raw_parts)]
|
#![feature(const_slice_from_raw_parts)]
|
||||||
|
Loading…
Reference in New Issue
Block a user