@@ -386,3 +386,164 @@ impl<T> FusedIterator for Once<T> {}
386
386
pub fn once < T > ( value : T ) -> Once < T > {
387
387
Once { inner : Some ( value) . into_iter ( ) }
388
388
}
389
+
390
+ /// Creates a new iterator where each iteration calls the provided closure
391
+ /// `F: FnMut(&mut St) -> Option<T>`.
392
+ ///
393
+ /// This allows creating a custom iterator with any behavior
394
+ /// without using the more verbose syntax of creating a dedicated type
395
+ /// and implementing the `Iterator` trait for it.
396
+ ///
397
+ /// In addition to its captures and environment,
398
+ /// the closure is given a mutable reference to some state
399
+ /// that is preserved across iterations.
400
+ /// That state starts as the given `initial_state` value.
401
+ ///
402
+ /// Note that the `Unfold` iterator doesn’t make assumptions about the behavior of the closure,
403
+ /// and therefore conservatively does not implement [`FusedIterator`],
404
+ /// or override [`Iterator::size_hint`] from its default `(0, None)`.
405
+ ///
406
+ /// [`FusedIterator`]: trait.FusedIterator.html
407
+ /// [`Iterator::size_hint`]: trait.Iterator.html#method.size_hint
408
+ ///
409
+ /// # Examples
410
+ ///
411
+ /// Let’s re-implement the counter iterator from [module-level documentation]:
412
+ ///
413
+ /// [module-level documentation]: index.html
414
+ ///
415
+ /// ```
416
+ /// #![feature(iter_unfold)]
417
+ /// let counter = std::iter::unfold(0, |count| {
418
+ /// // Increment our count. This is why we started at zero.
419
+ /// *count += 1;
420
+ ///
421
+ /// // Check to see if we've finished counting or not.
422
+ /// if *count < 6 {
423
+ /// Some(*count)
424
+ /// } else {
425
+ /// None
426
+ /// }
427
+ /// });
428
+ /// assert_eq!(counter.collect::<Vec<_>>(), &[1, 2, 3, 4, 5]);
429
+ /// ```
430
+ #[ inline]
431
+ #[ unstable( feature = "iter_unfold" , issue = "55977" ) ]
432
+ pub fn unfold < St , T , F > ( initial_state : St , f : F ) -> Unfold < St , F >
433
+ where F : FnMut ( & mut St ) -> Option < T >
434
+ {
435
+ Unfold {
436
+ state : initial_state,
437
+ f,
438
+ }
439
+ }
440
+
441
+ /// An iterator where each iteration calls the provided closure `F: FnMut(&mut St) -> Option<T>`.
442
+ ///
443
+ /// This `struct` is created by the [`unfold`] function.
444
+ /// See its documentation for more.
445
+ ///
446
+ /// [`unfold`]: fn.unfold.html
447
+ #[ derive( Clone ) ]
448
+ #[ unstable( feature = "iter_unfold" , issue = "55977" ) ]
449
+ pub struct Unfold < St , F > {
450
+ state : St ,
451
+ f : F ,
452
+ }
453
+
454
+ #[ unstable( feature = "iter_unfold" , issue = "55977" ) ]
455
+ impl < St , T , F > Iterator for Unfold < St , F >
456
+ where F : FnMut ( & mut St ) -> Option < T >
457
+ {
458
+ type Item = T ;
459
+
460
+ #[ inline]
461
+ fn next ( & mut self ) -> Option < Self :: Item > {
462
+ ( self . f ) ( & mut self . state )
463
+ }
464
+ }
465
+
466
+ #[ unstable( feature = "iter_unfold" , issue = "55977" ) ]
467
+ impl < St : fmt:: Debug , F > fmt:: Debug for Unfold < St , F > {
468
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
469
+ f. debug_struct ( "Unfold" )
470
+ . field ( "state" , & self . state )
471
+ . finish ( )
472
+ }
473
+ }
474
+
475
+ /// Creates a new iterator where each successive item is computed based on the preceding one.
476
+ ///
477
+ /// The iterator starts with the given first item (if any)
478
+ /// and calls the given `FnMut(&T) -> Option<T>` closure to compute each item’s successor.
479
+ ///
480
+ /// ```
481
+ /// #![feature(iter_unfold)]
482
+ /// use std::iter::successors;
483
+ ///
484
+ /// let powers_of_10 = successors(Some(1_u16), |n| n.checked_mul(10));
485
+ /// assert_eq!(powers_of_10.collect::<Vec<_>>(), &[1, 10, 100, 1_000, 10_000]);
486
+ /// ```
487
+ #[ unstable( feature = "iter_unfold" , issue = "55977" ) ]
488
+ pub fn successors < T , F > ( first : Option < T > , succ : F ) -> Successors < T , F >
489
+ where F : FnMut ( & T ) -> Option < T >
490
+ {
491
+ // If this function returned `impl Iterator<Item=T>`
492
+ // it could be based on `unfold` and not need a dedicated type.
493
+ // However having a named `Successors<T, F>` type allows it to be `Clone` when `T` and `F` are.
494
+ Successors {
495
+ next : first,
496
+ succ,
497
+ }
498
+ }
499
+
500
+ /// An new iterator where each successive item is computed based on the preceding one.
501
+ ///
502
+ /// This `struct` is created by the [`successors`] function.
503
+ /// See its documentation for more.
504
+ ///
505
+ /// [`successors`]: fn.successors.html
506
+ #[ derive( Clone ) ]
507
+ #[ unstable( feature = "iter_unfold" , issue = "55977" ) ]
508
+ pub struct Successors < T , F > {
509
+ next : Option < T > ,
510
+ succ : F ,
511
+ }
512
+
513
+ #[ unstable( feature = "iter_unfold" , issue = "55977" ) ]
514
+ impl < T , F > Iterator for Successors < T , F >
515
+ where F : FnMut ( & T ) -> Option < T >
516
+ {
517
+ type Item = T ;
518
+
519
+ #[ inline]
520
+ fn next ( & mut self ) -> Option < Self :: Item > {
521
+ self . next . take ( ) . map ( |item| {
522
+ self . next = ( self . succ ) ( & item) ;
523
+ item
524
+ } )
525
+ }
526
+
527
+ #[ inline]
528
+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
529
+ if self . next . is_some ( ) {
530
+ ( 1 , None )
531
+ } else {
532
+ ( 0 , Some ( 0 ) )
533
+ }
534
+ }
535
+ }
536
+
537
+ #[ unstable( feature = "iter_unfold" , issue = "55977" ) ]
538
+ impl < T , F > FusedIterator for Successors < T , F >
539
+ where F : FnMut ( & T ) -> Option < T >
540
+ { }
541
+
542
+ #[ unstable( feature = "iter_unfold" , issue = "55977" ) ]
543
+ impl < T : fmt:: Debug , F > fmt:: Debug for Successors < T , F > {
544
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
545
+ f. debug_struct ( "Successors" )
546
+ . field ( "next" , & self . next )
547
+ . finish ( )
548
+ }
549
+ }
0 commit comments