Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 641c490

Browse files
committedNov 20, 2018
Add std::iter::successors
1 parent 2222818 commit 641c490

File tree

4 files changed

+89
-1
lines changed

4 files changed

+89
-1
lines changed
 

‎src/libcore/iter/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ pub use self::sources::{Empty, empty};
340340
#[stable(feature = "iter_once", since = "1.2.0")]
341341
pub use self::sources::{Once, once};
342342
#[unstable(feature = "iter_unfold", issue = /* FIXME */ "0")]
343-
pub use self::sources::{Unfold, unfold};
343+
pub use self::sources::{Unfold, unfold, Successors, successors};
344344

345345
#[stable(feature = "rust1", since = "1.0.0")]
346346
pub use self::traits::{FromIterator, IntoIterator, DoubleEndedIterator, Extend};

‎src/libcore/iter/sources.rs

+76
Original file line numberDiff line numberDiff line change
@@ -471,3 +471,79 @@ impl<St: fmt::Debug, F> fmt::Debug for Unfold<St, F> {
471471
.finish()
472472
}
473473
}
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 = /* FIXME */ "0")]
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 = /* FIXME */ "0")]
508+
pub struct Successors<T, F> {
509+
next: Option<T>,
510+
succ: F,
511+
}
512+
513+
#[unstable(feature = "iter_unfold", issue = /* FIXME */ "0")]
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 = /* FIXME */ "0")]
538+
impl<T, F> FusedIterator for Successors<T, F>
539+
where F: FnMut(&T) -> Option<T>
540+
{}
541+
542+
#[unstable(feature = "iter_unfold", issue = /* FIXME */ "0")]
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+
}

‎src/libcore/tests/iter.rs

+11
Original file line numberDiff line numberDiff line change
@@ -1759,6 +1759,17 @@ fn test_repeat_with_take_collect() {
17591759
assert_eq!(v, vec![1, 2, 4, 8, 16]);
17601760
}
17611761

1762+
#[test]
1763+
fn test_successors() {
1764+
let mut powers_of_10 = successors(Some(1_u16), |n| n.checked_mul(10));
1765+
assert_eq!(powers_of_10.by_ref().collect::<Vec<_>>(), &[1, 10, 100, 1_000, 10_000]);
1766+
assert_eq!(powers_of_10.next(), None);
1767+
1768+
let mut empty = successors(None::<u32>, |_| unimplemented!());
1769+
assert_eq!(empty.next(), None);
1770+
assert_eq!(empty.next(), None);
1771+
}
1772+
17621773
#[test]
17631774
fn test_fuse() {
17641775
let mut it = 0..3;

‎src/libcore/tests/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#![feature(flt2dec)]
2020
#![feature(fmt_internals)]
2121
#![feature(hashmap_internals)]
22+
#![feature(iter_unfold)]
2223
#![feature(pattern)]
2324
#![feature(range_is_empty)]
2425
#![feature(raw)]

0 commit comments

Comments
 (0)
Please sign in to comment.