@@ -2525,15 +2525,7 @@ pub trait Iterator {
25252525 R : Try < Output = Self :: Item > ,
25262526 R :: Residual : Residual < Option < Self :: Item > > ,
25272527 {
2528- let first = match self . next ( ) {
2529- Some ( i) => i,
2530- None => return Try :: from_output ( None ) ,
2531- } ;
2532-
2533- match self . try_fold ( first, f) . branch ( ) {
2534- ControlFlow :: Break ( r) => FromResidual :: from_residual ( r) ,
2535- ControlFlow :: Continue ( i) => Try :: from_output ( Some ( i) ) ,
2536- }
2528+ self . try_fold_first ( Try :: from_output, f)
25372529 }
25382530
25392531 /// Folds every element into an accumulator by applying an operation,
@@ -2583,6 +2575,82 @@ pub trait Iterator {
25832575 Some ( self . fold ( first, folding) )
25842576 }
25852577
2578+ /// Folds every element into an accumulator by applying an operation,
2579+ /// returning the final result. The initial value is derived from the
2580+ /// first element using the provided method.
2581+ ///
2582+ /// If the closure returns a failure, the failure is propagated back to the caller immediately.
2583+ ///
2584+ /// # Example
2585+ ///
2586+ /// Replaying a series of events from creation
2587+ ///
2588+ /// ```
2589+ /// #![feature(iterator_try_fold_first)]
2590+ ///
2591+ /// enum Events {
2592+ /// Create,
2593+ /// Update,
2594+ /// }
2595+ ///
2596+ /// let events = [Events::Create, Events::Update, Events::Update];
2597+ /// let replayed_state = events.into_iter()
2598+ /// .try_fold_first(
2599+ /// |first| match first {
2600+ /// Events::Create => Ok(1),
2601+ /// _ => Err("only creation event supported at start"),
2602+ /// },
2603+ /// |state, next| match next {
2604+ /// Events::Update => Ok(state + 1),
2605+ /// _ => Err("only update events should follow a creation"),
2606+ /// },
2607+ /// );
2608+ /// assert_eq!(replayed_state, Ok(Some(3)));
2609+ ///
2610+ /// // Which is equivalent to doing it with `try_fold`:
2611+ /// let events = [Events::Create, Events::Update, Events::Update];
2612+ /// let folded = events.into_iter()
2613+ /// .try_fold(
2614+ /// None,
2615+ /// |state, event| {
2616+ /// match (state, event) {
2617+ /// // init
2618+ /// (None, Events::Create) => Ok(Some(1)),
2619+ /// (None, Events::Update) => Err("only update events should follow a creation"),
2620+ ///
2621+ /// // fold
2622+ /// (Some(state), Events::Update) => Ok(Some(state + 1)),
2623+ /// (Some(_), Events::Create) => Err("only creation event supported at start"),
2624+ /// }
2625+ /// },
2626+ /// );
2627+ /// assert_eq!(replayed_state, folded);
2628+ /// ```
2629+ #[ inline]
2630+ #[ unstable( feature = "iterator_try_fold_first" , reason = "new API" , issue = "none" ) ]
2631+ fn try_fold_first < F1 , FR , R > (
2632+ & mut self ,
2633+ init : F1 ,
2634+ folding : FR ,
2635+ ) -> ChangeOutputType < R , Option < R :: Output > >
2636+ where
2637+ Self : Sized ,
2638+ F1 : FnOnce ( Self :: Item ) -> R ,
2639+ FR : FnMut ( R :: Output , Self :: Item ) -> R ,
2640+ R : Try ,
2641+ R :: Residual : Residual < Option < R :: Output > > ,
2642+ {
2643+ let first = match self . next ( ) {
2644+ Some ( i) => init ( i) ?,
2645+ None => return Try :: from_output ( None ) ,
2646+ } ;
2647+
2648+ match self . try_fold ( first, folding) . branch ( ) {
2649+ ControlFlow :: Break ( r) => FromResidual :: from_residual ( r) ,
2650+ ControlFlow :: Continue ( i) => Try :: from_output ( Some ( i) ) ,
2651+ }
2652+ }
2653+
25862654 /// Tests if every element of the iterator matches a predicate.
25872655 ///
25882656 /// `all()` takes a closure that returns `true` or `false`. It applies
0 commit comments