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 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
// 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. pub struct Unfold<F, S> { f: F, value: S, } impl<F, S, A> Iterator for Unfold<F, S> where F: Fn(&S) -> Option<(A, S)>, { type Item = A; fn next(&mut self) -> Option<Self::Item> { match (self.f)(&self.value) { None => None, Some((next, value)) => { self.value = value; Some(next) } } } } pub struct UnfoldMut<F, S> { f: F, value: S, } impl<F, S, A> Iterator for UnfoldMut<F, S> where F: Fn(&mut S) -> Option<A>, { type Item = A; fn next(&mut self) -> Option<Self::Item> { (self.f)(&mut self.value) } } /// Create an iterator of values using a function to update a 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 im; /// # use im::iter::unfold; /// # use im::vector::Vector; /// # use std::iter::FromIterator; /// # fn main() { /// // 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 #[must_use] pub fn unfold<F, S, A>(value: S, f: F) -> Unfold<F, S> where F: Fn(&S) -> Option<(A, S)>, { Unfold { f, value } } /// Create an iterator of values using a function to mutate a state /// value. /// /// The function is called with a mutable reference to the current /// state as its argument, and should return an /// [`Option`][std::option::Option] of the next value to yield from /// the iterator, updating the state as necessary. If the function /// returns [`None`][std::option::Option::None], the iterator ends. /// /// This differs from [`unfold`][unfold] in that your update functions /// will probably be less elegant, but it's easier to deal with state /// that isn't efficiently cloneable. /// /// # Examples /// ``` /// # #[macro_use] extern crate im; /// # use im::iter::unfold_mut; /// # use im::vector::Vector; /// # use std::iter::FromIterator; /// # fn main() { /// // Create an infinite stream of numbers, starting at 0. /// let mut it = unfold_mut(0, |i| { /// let next = *i; /// *i += 1; /// Some(next) /// }); /// /// // 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 /// [unfold]: ./fn.unfold.html #[must_use] pub fn unfold_mut<F, S, A>(value: S, f: F) -> UnfoldMut<F, S> where F: Fn(&mut S) -> Option<A>, { UnfoldMut { f, value } }