Skip to content

Commit

Permalink
Adopt Unfold from rust, since it is deprecated there
Browse files Browse the repository at this point in the history
Original author credit for Unfold (UnfoldrIterator in the first
revision) is @huonw.
  • Loading branch information
root committed Jun 22, 2015
1 parent 16e3d48 commit edc9295
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 2 deletions.
5 changes: 3 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
//! ```
//!
//! Some iterators or adaptors are used directly like regular structs, for example
//! [**PutBack**](./struct.PutBack.html), [**Zip**](./struct.Zip.html),
//! [**Stride**](./struct.Stride.html), [**StrideMut**](./struct.StrideMut.html).
//! [**PutBack**](./struct.PutBack.html), [**Unfold**](./struct.Unfold.html),
//! [**Zip**](./struct.Zip.html), [**Stride**](./struct.Stride.html)
//!
//! To enable the macros in this crate, use the `#[macro_use]` attribute:
//!
Expand Down Expand Up @@ -73,6 +73,7 @@ pub use times::times;
pub use linspace::{linspace, Linspace};
pub use sources::{
RepeatCall,
Unfold,
};
pub use zip_longest::{ZipLongest, EitherOrBoth};
pub use ziptuple::{Zip};
Expand Down
72 changes: 72 additions & 0 deletions src/sources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,75 @@ impl<A, F> DoubleEndedIterator for RepeatCall<F> where
}


/// **Unfold** is a general iterator builder: it has a mutable state value,
/// and a closure with access to the state that produces the next value.
///
/// This more or less equivalent to a regular struct with an **Iterator**
/// implementation, and is useful for one-off iterators.
///
/// ```
/// // an example of iterator that yields sequential Fibonacci numbers, and stops
/// // on overflow.
/// use itertools::Unfold;
///
/// // This iterator will yield up to the last Fibonacci number before the max
/// // value of `u32`. You can simply change `u32` to `u64` in this line if
/// // you want higher values than that.
/// let mut fibonacci = Unfold::new((Some(0u32), Some(1u32)),
/// |&mut (ref mut x2, ref mut x1)| {
/// // Attempt to get the next Fibonacci number
/// // `x1` will be `None` if previously overflowed.
/// let next = match (*x2, *x1) {
/// (Some(x2), Some(x1)) => x2.checked_add(x1),
/// _ => None,
/// };
///
/// // Shift left: ret <- x2 <- x1 <- next
/// let ret = *x2;
/// *x2 = *x1;
/// *x1 = next;
///
/// ret
/// });
///
/// itertools::assert_equal(fibonacci.take(8),
/// vec![0, 1, 1, 2, 3, 5, 8, 13]);
/// ```
#[derive(Clone)]
pub struct Unfold<St, F> {
f: F,
/// Internal state that will be passed to the closure on the next iteration
pub state: St,
}

impl<A, St, F> Unfold<St, F>
where F: FnMut(&mut St) -> Option<A>
{
/// Creates a new iterator with the specified closure as the "iterator
/// function" and an initial state to eventually pass to the closure
#[inline]
pub fn new(initial_state: St, f: F) -> Unfold<St, F> {
Unfold {
f: f,
state: initial_state
}
}
}

impl<A, St, F> Iterator for Unfold<St, F>
where F: FnMut(&mut St) -> Option<A>
{
type Item = A;

#[inline]
fn next(&mut self) -> Option<A> {
(self.f)(&mut self.state)
}

#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
// no possible known bounds at this point
(0, None)
}
}

0 comments on commit edc9295

Please sign in to comment.