@@ -2216,6 +2216,86 @@ pub trait Iterator {
2216
2216
Some ( self . fold ( first, f) )
2217
2217
}
2218
2218
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
+
2219
2299
/// Tests if every element of the iterator matches a predicate.
2220
2300
///
2221
2301
/// `all()` takes a closure that returns `true` or `false`. It applies
0 commit comments