Skip to content

Instantly share code, notes, and snippets.

@jimblandy
Created June 13, 2018 04:47
Show Gist options
  • Save jimblandy/4142c24d7bda3ae76cf7638b085c632e to your computer and use it in GitHub Desktop.
Save jimblandy/4142c24d7bda3ae76cf7638b085c632e to your computer and use it in GitHub Desktop.
A Rust `unfold` function, to build an iterator by repeatedly applying a closure.
fn main() {
//let i = (0i32..).scan((0,1), |s,_| { *s = (s.1, s.0 + s.1); Some(s.0) });
let i = unfold((0, 1), |(a, b)| Some(((b, a+b), b)));
let v: Vec<i32> = i.take(20).collect();
println!("{:?}", v);
}
struct Unfolder<F, T>(F, Option<T>);
impl<T, U, F> Iterator for Unfolder<F, T>
where F: FnMut(T) -> Option<(T, U)>
{
type Item = U;
fn next(&mut self) -> Option<U> {
self.1.take()
.map_or(None, &mut self.0)
.map_or(None, |(next_v, item)| {
self.1 = Some(next_v);
Some(item)
})
}
}
fn unfold<T, U, F>(t: T, f: F) -> impl Iterator<Item=U>
where F: FnMut(T) -> Option<(T, U)>
{
Unfolder(f, Some(t))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment