imbl/iter.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//! Iterators over immutable data.
/// Create an iterator of values using a function to update an owned state
/// value.
///
/// The function is called with the current state as its argument, and should
/// return an [`Option`][std::option::Option] of a tuple of the next value to
/// yield from the iterator and the updated state. If the function returns
/// [`None`][std::option::Option::None], the iterator ends.
///
/// # Examples
/// ```
/// # #[macro_use] extern crate imbl;
/// # use imbl::iter::unfold;
/// # use imbl::vector::Vector;
/// # use std::iter::FromIterator;
/// // Create an infinite stream of numbers, starting at 0.
/// let mut it = unfold(0, |i| Some((i, i + 1)));
///
/// // Make a list out of its first five elements.
/// let numbers = Vector::from_iter(it.take(5));
/// assert_eq!(numbers, vector![0, 1, 2, 3, 4]);
/// ```
///
/// [std::option::Option]: https://doc.rust-lang.org/std/option/enum.Option.html
/// [std::option::Option::None]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None
pub fn unfold<F, S, A>(value: S, f: F) -> impl Iterator<Item = A>
where
F: Fn(S) -> Option<(A, S)>,
{
let mut value = Some(value);
std::iter::from_fn(move || {
f(value.take().unwrap()).map(|(next, state)| {
value = Some(state);
next
})
})
}