9
9
// except according to those terms.
10
10
11
11
use cmp:: Ordering ;
12
+ use ops:: Try ;
12
13
14
+ use super :: { AlwaysOk , LoopState } ;
13
15
use super :: { Chain , Cycle , Cloned , Enumerate , Filter , FilterMap , FlatMap , Fuse } ;
14
16
use super :: { Inspect , Map , Peekable , Scan , Skip , SkipWhile , StepBy , Take , TakeWhile , Rev } ;
15
17
use super :: { Zip , Sum , Product } ;
@@ -251,12 +253,8 @@ pub trait Iterator {
251
253
/// ```
252
254
#[ inline]
253
255
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
254
- fn nth ( & mut self , mut n : usize ) -> Option < Self :: Item > {
255
- for x in self {
256
- if n == 0 { return Some ( x) }
257
- n -= 1 ;
258
- }
259
- None
256
+ fn nth ( & mut self , n : usize ) -> Option < Self :: Item > {
257
+ self . spec_nth ( n)
260
258
}
261
259
262
260
/// Creates an iterator starting at the same point, but stepping by
@@ -1337,6 +1335,78 @@ pub trait Iterator {
1337
1335
( left, right)
1338
1336
}
1339
1337
1338
+ /// An iterator method that applies a function as long as it returns
1339
+ /// successfully, producing a single, final value.
1340
+ ///
1341
+ /// `try_fold()` takes two arguments: an initial value, and a closure with
1342
+ /// two arguments: an 'accumulator', and an element. The closure either
1343
+ /// returns successfully, with the value that the accumulator should have
1344
+ /// for the next iteration, or it returns failure, with an error value that
1345
+ /// is propagated back to the caller immediately (short-circuiting).
1346
+ ///
1347
+ /// The initial value is the value the accumulator will have on the first
1348
+ /// call. If applying the closure succeeded against every element of the
1349
+ /// iterator, `try_fold()` returns the final accumulator as success.
1350
+ ///
1351
+ /// Folding is useful whenever you have a collection of something, and want
1352
+ /// to produce a single value from it.
1353
+ ///
1354
+ /// # Note to Implementors
1355
+ ///
1356
+ /// Most of the other (forward) methods have default implementations in
1357
+ /// terms of this one, so try to implement this explicitly if it can
1358
+ /// do something better than the default `for` loop implementation.
1359
+ ///
1360
+ /// In particular, try to have this call `try_fold()` on the internal parts
1361
+ /// from which this iterator is composed. If multiple calls are needed,
1362
+ /// the `?` operator be convenient for chaining the accumulator value along,
1363
+ /// but beware any invariants that need to be upheld before those early
1364
+ /// returns. This is a `&mut self` method, so iteration needs to be
1365
+ /// resumable after hitting an error here.
1366
+ ///
1367
+ /// # Examples
1368
+ ///
1369
+ /// Basic usage:
1370
+ ///
1371
+ /// ```
1372
+ /// #![feature(iterator_try_fold)]
1373
+ /// let a = [1, 2, 3];
1374
+ ///
1375
+ /// // the checked sum of all of the elements of the array
1376
+ /// let sum = a.iter()
1377
+ /// .try_fold(0i8, |acc, &x| acc.checked_add(x));
1378
+ ///
1379
+ /// assert_eq!(sum, Some(6));
1380
+ /// ```
1381
+ ///
1382
+ /// Short-circuiting:
1383
+ ///
1384
+ /// ```
1385
+ /// #![feature(iterator_try_fold)]
1386
+ /// let a = [10, 20, 30, 100, 40, 50];
1387
+ /// let mut it = a.iter();
1388
+ ///
1389
+ /// // This sum overflows when adding the 100 element
1390
+ /// let sum = it.try_fold(0i8, |acc, &x| acc.checked_add(x));
1391
+ /// assert_eq!(sum, None);
1392
+ ///
1393
+ /// // Because it short-circuited, the remaining elements are still
1394
+ /// // available through the iterator.
1395
+ /// assert_eq!(it.len(), 2);
1396
+ /// assert_eq!(it.next(), Some(&40));
1397
+ /// ```
1398
+ #[ inline]
1399
+ #[ unstable( feature = "iterator_try_fold" , issue = "45594" ) ]
1400
+ fn try_fold < B , F , R > ( & mut self , init : B , mut f : F ) -> R where
1401
+ Self : Sized , F : FnMut ( B , Self :: Item ) -> R , R : Try < Ok =B >
1402
+ {
1403
+ let mut accum = init;
1404
+ while let Some ( x) = self . next ( ) {
1405
+ accum = f ( accum, x) ?;
1406
+ }
1407
+ Try :: from_ok ( accum)
1408
+ }
1409
+
1340
1410
/// An iterator method that applies a function, producing a single, final value.
1341
1411
///
1342
1412
/// `fold()` takes two arguments: an initial value, and a closure with two
@@ -1361,7 +1431,7 @@ pub trait Iterator {
1361
1431
/// ```
1362
1432
/// let a = [1, 2, 3];
1363
1433
///
1364
- /// // the sum of all of the elements of a
1434
+ /// // the sum of all of the elements of the array
1365
1435
/// let sum = a.iter()
1366
1436
/// .fold(0, |acc, &x| acc + x);
1367
1437
///
@@ -1403,14 +1473,10 @@ pub trait Iterator {
1403
1473
/// ```
1404
1474
#[ inline]
1405
1475
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1406
- fn fold < B , F > ( self , init : B , mut f : F ) -> B where
1476
+ fn fold < B , F > ( mut self , init : B , mut f : F ) -> B where
1407
1477
Self : Sized , F : FnMut ( B , Self :: Item ) -> B ,
1408
1478
{
1409
- let mut accum = init;
1410
- for x in self {
1411
- accum = f ( accum, x) ;
1412
- }
1413
- accum
1479
+ self . try_fold ( init, move |acc, x| AlwaysOk ( f ( acc, x) ) ) . 0
1414
1480
}
1415
1481
1416
1482
/// Tests if every element of the iterator matches a predicate.
@@ -1455,12 +1521,10 @@ pub trait Iterator {
1455
1521
fn all < F > ( & mut self , mut f : F ) -> bool where
1456
1522
Self : Sized , F : FnMut ( Self :: Item ) -> bool
1457
1523
{
1458
- for x in self {
1459
- if !f ( x) {
1460
- return false ;
1461
- }
1462
- }
1463
- true
1524
+ self . try_fold ( ( ) , move |( ) , x| {
1525
+ if f ( x) { LoopState :: Continue ( ( ) ) }
1526
+ else { LoopState :: Break ( ( ) ) }
1527
+ } ) == LoopState :: Continue ( ( ) )
1464
1528
}
1465
1529
1466
1530
/// Tests if any element of the iterator matches a predicate.
@@ -1506,12 +1570,10 @@ pub trait Iterator {
1506
1570
Self : Sized ,
1507
1571
F : FnMut ( Self :: Item ) -> bool
1508
1572
{
1509
- for x in self {
1510
- if f ( x) {
1511
- return true ;
1512
- }
1513
- }
1514
- false
1573
+ self . try_fold ( ( ) , move |( ) , x| {
1574
+ if f ( x) { LoopState :: Break ( ( ) ) }
1575
+ else { LoopState :: Continue ( ( ) ) }
1576
+ } ) == LoopState :: Break ( ( ) )
1515
1577
}
1516
1578
1517
1579
/// Searches for an element of an iterator that satisfies a predicate.
@@ -1562,10 +1624,10 @@ pub trait Iterator {
1562
1624
Self : Sized ,
1563
1625
P : FnMut ( & Self :: Item ) -> bool ,
1564
1626
{
1565
- for x in self {
1566
- if predicate ( & x) { return Some ( x) }
1567
- }
1568
- None
1627
+ self . try_fold ( ( ) , move | ( ) , x| {
1628
+ if predicate ( & x) { LoopState :: Break ( x) }
1629
+ else { LoopState :: Continue ( ( ) ) }
1630
+ } ) . break_value ( )
1569
1631
}
1570
1632
1571
1633
/// Searches for an element in an iterator, returning its index.
@@ -1623,18 +1685,17 @@ pub trait Iterator {
1623
1685
///
1624
1686
/// ```
1625
1687
#[ inline]
1688
+ #[ rustc_inherit_overflow_checks]
1626
1689
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1627
1690
fn position < P > ( & mut self , mut predicate : P ) -> Option < usize > where
1628
1691
Self : Sized ,
1629
1692
P : FnMut ( Self :: Item ) -> bool ,
1630
1693
{
1631
- // `enumerate` might overflow.
1632
- for ( i, x) in self . enumerate ( ) {
1633
- if predicate ( x) {
1634
- return Some ( i) ;
1635
- }
1636
- }
1637
- None
1694
+ // The addition might panic on overflow
1695
+ self . try_fold ( 0 , move |i, x| {
1696
+ if predicate ( x) { LoopState :: Break ( i) }
1697
+ else { LoopState :: Continue ( i + 1 ) }
1698
+ } ) . break_value ( )
1638
1699
}
1639
1700
1640
1701
/// Searches for an element in an iterator from the right, returning its
@@ -1681,17 +1742,14 @@ pub trait Iterator {
1681
1742
P : FnMut ( Self :: Item ) -> bool ,
1682
1743
Self : Sized + ExactSizeIterator + DoubleEndedIterator
1683
1744
{
1684
- let mut i = self . len ( ) ;
1685
-
1686
- while let Some ( v) = self . next_back ( ) {
1687
- // No need for an overflow check here, because `ExactSizeIterator`
1688
- // implies that the number of elements fits into a `usize`.
1689
- i -= 1 ;
1690
- if predicate ( v) {
1691
- return Some ( i) ;
1692
- }
1693
- }
1694
- None
1745
+ // No need for an overflow check here, because `ExactSizeIterator`
1746
+ // implies that the number of elements fits into a `usize`.
1747
+ let n = self . len ( ) ;
1748
+ self . try_rfold ( n, move |i, x| {
1749
+ let i = i - 1 ;
1750
+ if predicate ( x) { LoopState :: Break ( i) }
1751
+ else { LoopState :: Continue ( i) }
1752
+ } ) . break_value ( )
1695
1753
}
1696
1754
1697
1755
/// Returns the maximum element of an iterator.
@@ -1922,10 +1980,10 @@ pub trait Iterator {
1922
1980
let mut ts: FromA = Default :: default ( ) ;
1923
1981
let mut us: FromB = Default :: default ( ) ;
1924
1982
1925
- for ( t, u) in self {
1983
+ self . for_each ( | ( t, u) | {
1926
1984
ts. extend ( Some ( t) ) ;
1927
1985
us. extend ( Some ( u) ) ;
1928
- }
1986
+ } ) ;
1929
1987
1930
1988
( ts, us)
1931
1989
}
@@ -2300,17 +2358,17 @@ fn select_fold1<I, B, FProj, FCmp>(mut it: I,
2300
2358
// start with the first element as our selection. This avoids
2301
2359
// having to use `Option`s inside the loop, translating to a
2302
2360
// sizeable performance gain (6x in one case).
2303
- it. next ( ) . map ( |mut sel | {
2304
- let mut sel_p = f_proj ( & sel ) ;
2361
+ it. next ( ) . map ( |first | {
2362
+ let first_p = f_proj ( & first ) ;
2305
2363
2306
- for x in it {
2364
+ it . fold ( ( first_p , first ) , | ( sel_p , sel ) , x| {
2307
2365
let x_p = f_proj ( & x) ;
2308
2366
if f_cmp ( & sel_p, & sel, & x_p, & x) {
2309
- sel = x;
2310
- sel_p = x_p;
2367
+ ( x_p, x)
2368
+ } else {
2369
+ ( sel_p, sel)
2311
2370
}
2312
- }
2313
- ( sel_p, sel)
2371
+ } )
2314
2372
} )
2315
2373
}
2316
2374
@@ -2323,3 +2381,27 @@ impl<'a, I: Iterator + ?Sized> Iterator for &'a mut I {
2323
2381
( * * self ) . nth ( n)
2324
2382
}
2325
2383
}
2384
+
2385
+
2386
+ trait SpecIterator : Iterator {
2387
+ fn spec_nth ( & mut self , n : usize ) -> Option < Self :: Item > ;
2388
+ }
2389
+
2390
+ impl < I : Iterator + ?Sized > SpecIterator for I {
2391
+ default fn spec_nth ( & mut self , mut n : usize ) -> Option < Self :: Item > {
2392
+ for x in self {
2393
+ if n == 0 { return Some ( x) }
2394
+ n -= 1 ;
2395
+ }
2396
+ None
2397
+ }
2398
+ }
2399
+
2400
+ impl < I : Iterator + Sized > SpecIterator for I {
2401
+ fn spec_nth ( & mut self , n : usize ) -> Option < Self :: Item > {
2402
+ self . try_fold ( n, move |i, x| {
2403
+ if i == 0 { LoopState :: Break ( x) }
2404
+ else { LoopState :: Continue ( i - 1 ) }
2405
+ } ) . break_value ( )
2406
+ }
2407
+ }
0 commit comments