@@ -2525,15 +2525,7 @@ pub trait Iterator {
2525
2525
R : Try < Output = Self :: Item > ,
2526
2526
R :: Residual : Residual < Option < Self :: Item > > ,
2527
2527
{
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)
2537
2529
}
2538
2530
2539
2531
/// Folds every element into an accumulator by applying an operation,
@@ -2583,6 +2575,82 @@ pub trait Iterator {
2583
2575
Some ( self . fold ( first, folding) )
2584
2576
}
2585
2577
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
+
2586
2654
/// Tests if every element of the iterator matches a predicate.
2587
2655
///
2588
2656
/// `all()` takes a closure that returns `true` or `false`. It applies
0 commit comments