@@ -2216,6 +2216,86 @@ pub trait Iterator {
22162216 Some ( self . fold ( first, f) )
22172217 }
22182218
2219+ /// Reduces the elements to a single one by repeatedly applying a reducing operation. If the
2220+ /// closure returns a failure, the failure is propagated back to the caller immediately.
2221+ ///
2222+ /// The return type of this method depends on the return type of the closure. If the closure
2223+ /// returns `Result<Self::Item, E>`, then this function will return `Result<Option<Self::Item>,
2224+ /// E>`. If the closure returns `Option<Self::Item>`, then this function will return
2225+ /// `Option<Option<Self::Item>>`.
2226+ ///
2227+ /// When called on an empty iterator, this function will return either `Some(None)` or
2228+ /// `Ok(None)` depending on the type of the provided closure.
2229+ ///
2230+ /// For iterators with at least one element, this is essentially the same as calling
2231+ /// [`try_fold()`] with the first element of the iterator as the initial accumulator value.
2232+ ///
2233+ /// [`try_fold()`]: Iterator::try_fold
2234+ ///
2235+ /// # Examples
2236+ ///
2237+ /// Safely calculate the sum of a series of numbers:
2238+ ///
2239+ /// ```
2240+ /// #![feature(iterator_try_reduce)]
2241+ ///
2242+ /// let numbers: Vec<usize> = vec![10, 20, 5, 23, 0];
2243+ /// let sum = numbers.into_iter().try_reduce(|x, y| x.checked_add(y));
2244+ /// assert_eq!(sum, Some(Some(58)));
2245+ /// ```
2246+ ///
2247+ /// Determine when a reduction short circuited:
2248+ ///
2249+ /// ```
2250+ /// #![feature(iterator_try_reduce)]
2251+ ///
2252+ /// let numbers = vec![1, 2, 3, usize::MAX, 4, 5];
2253+ /// let sum = numbers.into_iter().try_reduce(|x, y| x.checked_add(y));
2254+ /// assert_eq!(sum, None);
2255+ /// ```
2256+ ///
2257+ /// Determine when a reduction was not performed because there are no elements:
2258+ ///
2259+ /// ```
2260+ /// #![feature(iterator_try_reduce)]
2261+ ///
2262+ /// let numbers: Vec<usize> = Vec::new();
2263+ /// let sum = numbers.into_iter().try_reduce(|x, y| x.checked_add(y));
2264+ /// assert_eq!(sum, Some(None));
2265+ /// ```
2266+ ///
2267+ /// Use a [`Result`] instead of an [`Option`]:
2268+ ///
2269+ /// ```
2270+ /// #![feature(iterator_try_reduce)]
2271+ ///
2272+ /// let numbers = vec!["1", "2", "3", "4", "5"];
2273+ /// let max: Result<Option<_>, <usize as std::str::FromStr>::Err> =
2274+ /// numbers.into_iter().try_reduce(|x, y| {
2275+ /// if x.parse::<usize>()? > y.parse::<usize>()? { Ok(x) } else { Ok(y) }
2276+ /// });
2277+ /// assert_eq!(max, Ok(Some("5")));
2278+ /// ```
2279+ #[ inline]
2280+ #[ unstable( feature = "iterator_try_reduce" , reason = "new API" , issue = "87053" ) ]
2281+ fn try_reduce < F , R > ( & mut self , f : F ) -> ChangeOutputType < R , Option < R :: Output > >
2282+ where
2283+ Self : Sized ,
2284+ F : FnMut ( Self :: Item , Self :: Item ) -> R ,
2285+ R : Try < Output = Self :: Item > ,
2286+ R :: Residual : Residual < Option < Self :: Item > > ,
2287+ {
2288+ let first = match self . next ( ) {
2289+ Some ( i) => i,
2290+ None => return Try :: from_output ( None ) ,
2291+ } ;
2292+
2293+ match self . try_fold ( first, f) . branch ( ) {
2294+ ControlFlow :: Break ( r) => FromResidual :: from_residual ( r) ,
2295+ ControlFlow :: Continue ( i) => Try :: from_output ( Some ( i) ) ,
2296+ }
2297+ }
2298+
22192299 /// Tests if every element of the iterator matches a predicate.
22202300 ///
22212301 /// `all()` takes a closure that returns `true` or `false`. It applies
0 commit comments