Skip to content

Commit edc9295

Browse files
author
root
committed
Adopt Unfold from rust, since it is deprecated there
Original author credit for Unfold (UnfoldrIterator in the first revision) is @huonw.
1 parent 16e3d48 commit edc9295

File tree

2 files changed

+75
-2
lines changed

2 files changed

+75
-2
lines changed

src/lib.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
//! ```
1212
//!
1313
//! Some iterators or adaptors are used directly like regular structs, for example
14-
//! [**PutBack**](./struct.PutBack.html), [**Zip**](./struct.Zip.html),
15-
//! [**Stride**](./struct.Stride.html), [**StrideMut**](./struct.StrideMut.html).
14+
//! [**PutBack**](./struct.PutBack.html), [**Unfold**](./struct.Unfold.html),
15+
//! [**Zip**](./struct.Zip.html), [**Stride**](./struct.Stride.html)
1616
//!
1717
//! To enable the macros in this crate, use the `#[macro_use]` attribute:
1818
//!
@@ -73,6 +73,7 @@ pub use times::times;
7373
pub use linspace::{linspace, Linspace};
7474
pub use sources::{
7575
RepeatCall,
76+
Unfold,
7677
};
7778
pub use zip_longest::{ZipLongest, EitherOrBoth};
7879
pub use ziptuple::{Zip};

src/sources.rs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,75 @@ impl<A, F> DoubleEndedIterator for RepeatCall<F> where
5959
}
6060

6161

62+
/// **Unfold** is a general iterator builder: it has a mutable state value,
63+
/// and a closure with access to the state that produces the next value.
64+
///
65+
/// This more or less equivalent to a regular struct with an **Iterator**
66+
/// implementation, and is useful for one-off iterators.
67+
///
68+
/// ```
69+
/// // an example of iterator that yields sequential Fibonacci numbers, and stops
70+
/// // on overflow.
71+
/// use itertools::Unfold;
72+
///
73+
/// // This iterator will yield up to the last Fibonacci number before the max
74+
/// // value of `u32`. You can simply change `u32` to `u64` in this line if
75+
/// // you want higher values than that.
76+
/// let mut fibonacci = Unfold::new((Some(0u32), Some(1u32)),
77+
/// |&mut (ref mut x2, ref mut x1)| {
78+
/// // Attempt to get the next Fibonacci number
79+
/// // `x1` will be `None` if previously overflowed.
80+
/// let next = match (*x2, *x1) {
81+
/// (Some(x2), Some(x1)) => x2.checked_add(x1),
82+
/// _ => None,
83+
/// };
84+
///
85+
/// // Shift left: ret <- x2 <- x1 <- next
86+
/// let ret = *x2;
87+
/// *x2 = *x1;
88+
/// *x1 = next;
89+
///
90+
/// ret
91+
/// });
92+
///
93+
/// itertools::assert_equal(fibonacci.take(8),
94+
/// vec![0, 1, 1, 2, 3, 5, 8, 13]);
95+
/// ```
96+
#[derive(Clone)]
97+
pub struct Unfold<St, F> {
98+
f: F,
99+
/// Internal state that will be passed to the closure on the next iteration
100+
pub state: St,
101+
}
102+
103+
impl<A, St, F> Unfold<St, F>
104+
where F: FnMut(&mut St) -> Option<A>
105+
{
106+
/// Creates a new iterator with the specified closure as the "iterator
107+
/// function" and an initial state to eventually pass to the closure
108+
#[inline]
109+
pub fn new(initial_state: St, f: F) -> Unfold<St, F> {
110+
Unfold {
111+
f: f,
112+
state: initial_state
113+
}
114+
}
115+
}
116+
117+
impl<A, St, F> Iterator for Unfold<St, F>
118+
where F: FnMut(&mut St) -> Option<A>
119+
{
120+
type Item = A;
121+
122+
#[inline]
123+
fn next(&mut self) -> Option<A> {
124+
(self.f)(&mut self.state)
125+
}
126+
127+
#[inline]
128+
fn size_hint(&self) -> (usize, Option<usize>) {
129+
// no possible known bounds at this point
130+
(0, None)
131+
}
132+
}
133+

0 commit comments

Comments
 (0)