Skip to content

Commit 48aae09

Browse files
committed
Add std::iter::unfold
1 parent 15e6613 commit 48aae09

File tree

2 files changed

+78
-0
lines changed

2 files changed

+78
-0
lines changed

src/libcore/iter/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,8 @@ pub use self::sources::{RepeatWith, repeat_with};
339339
pub use self::sources::{Empty, empty};
340340
#[stable(feature = "iter_once", since = "1.2.0")]
341341
pub use self::sources::{Once, once};
342+
#[unstable(feature = "iter_unfold", issue = /* FIXME */ "0")]
343+
pub use self::sources::{Unfold, unfold};
342344

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

src/libcore/iter/sources.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,3 +386,79 @@ impl<T> FusedIterator for Once<T> {}
386386
pub fn once<T>(value: T) -> Once<T> {
387387
Once { inner: Some(value).into_iter() }
388388
}
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 = /* FIXME */ "0")]
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(Copy, Clone, Debug)]
448+
#[unstable(feature = "iter_unfold", issue = /* FIXME */ "0")]
449+
pub struct Unfold<St, F> {
450+
state: St,
451+
f: F,
452+
}
453+
454+
#[unstable(feature = "iter_unfold", issue = /* FIXME */ "0")]
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+
}

0 commit comments

Comments
 (0)