]>
Commit | Line | Data |
---|---|---|
abe05a73 XL |
1 | //! Iterators that are sources (produce elements from parameters, |
2 | //! not from another iterator). | |
3 | ||
4 | use std::fmt; | |
5 | use std::mem; | |
6 | ||
7 | /// See [`repeat_call`](../fn.repeat_call.html) for more information. | |
8 | pub struct RepeatCall<F> { | |
9 | f: F, | |
10 | } | |
11 | ||
12 | impl<F> fmt::Debug for RepeatCall<F> | |
13 | { | |
14 | debug_fmt_fields!(RepeatCall, ); | |
15 | } | |
16 | ||
17 | /// An iterator source that produces elements indefinitely by calling | |
18 | /// a given closure. | |
19 | /// | |
20 | /// Iterator element type is the return type of the closure. | |
21 | /// | |
22 | /// ``` | |
23 | /// use itertools::repeat_call; | |
24 | /// use itertools::Itertools; | |
25 | /// use std::collections::BinaryHeap; | |
26 | /// | |
27 | /// let mut heap = BinaryHeap::from(vec![2, 5, 3, 7, 8]); | |
28 | /// | |
29 | /// // extract each element in sorted order | |
30 | /// for element in repeat_call(|| heap.pop()).while_some() { | |
31 | /// print!("{}", element); | |
32 | /// } | |
33 | /// | |
34 | /// itertools::assert_equal( | |
35 | /// repeat_call(|| 1).take(5), | |
36 | /// vec![1, 1, 1, 1, 1] | |
37 | /// ); | |
38 | /// ``` | |
2c00a5a8 XL |
39 | pub fn repeat_call<F, A>(function: F) -> RepeatCall<F> |
40 | where F: FnMut() -> A | |
41 | { | |
abe05a73 XL |
42 | RepeatCall { f: function } |
43 | } | |
44 | ||
45 | impl<A, F> Iterator for RepeatCall<F> | |
46 | where F: FnMut() -> A | |
47 | { | |
48 | type Item = A; | |
49 | ||
50 | #[inline] | |
51 | fn next(&mut self) -> Option<A> { | |
52 | Some((self.f)()) | |
53 | } | |
54 | ||
55 | fn size_hint(&self) -> (usize, Option<usize>) { | |
56 | (usize::max_value(), None) | |
57 | } | |
58 | } | |
59 | ||
60 | /// Creates a new unfold source with the specified closure as the "iterator | |
61 | /// function" and an initial state to eventually pass to the closure | |
62 | /// | |
63 | /// `unfold` is a general iterator builder: it has a mutable state value, | |
64 | /// and a closure with access to the state that produces the next value. | |
65 | /// | |
66 | /// This more or less equivalent to a regular struct with an `Iterator` | |
67 | /// implementation, and is useful for one-off iterators. | |
68 | /// | |
69 | /// ``` | |
70 | /// // an iterator that yields sequential Fibonacci numbers, | |
71 | /// // and stops at the maximum representable value. | |
72 | /// | |
73 | /// use itertools::unfold; | |
74 | /// | |
75 | /// let (mut x1, mut x2) = (1u32, 1u32); | |
76 | /// let mut fibonacci = unfold((), move |_| { | |
77 | /// // Attempt to get the next Fibonacci number | |
78 | /// let next = x1.saturating_add(x2); | |
79 | /// | |
80 | /// // Shift left: ret <- x1 <- x2 <- next | |
81 | /// let ret = x1; | |
82 | /// x1 = x2; | |
83 | /// x2 = next; | |
84 | /// | |
85 | /// // If addition has saturated at the maximum, we are finished | |
86 | /// if ret == x1 && ret > 1 { | |
87 | /// return None; | |
88 | /// } | |
89 | /// | |
90 | /// Some(ret) | |
91 | /// }); | |
92 | /// | |
93 | /// itertools::assert_equal(fibonacci.by_ref().take(8), | |
94 | /// vec![1, 1, 2, 3, 5, 8, 13, 21]); | |
95 | /// assert_eq!(fibonacci.last(), Some(2_971_215_073)) | |
96 | /// ``` | |
97 | pub fn unfold<A, St, F>(initial_state: St, f: F) -> Unfold<St, F> | |
98 | where F: FnMut(&mut St) -> Option<A> | |
99 | { | |
100 | Unfold { | |
101 | f: f, | |
102 | state: initial_state, | |
103 | } | |
104 | } | |
105 | ||
106 | impl<St, F> fmt::Debug for Unfold<St, F> | |
107 | where St: fmt::Debug, | |
108 | { | |
109 | debug_fmt_fields!(Unfold, state); | |
110 | } | |
111 | ||
112 | /// See [`unfold`](../fn.unfold.html) for more information. | |
113 | #[derive(Clone)] | |
2c00a5a8 | 114 | #[must_use = "iterators are lazy and do nothing unless consumed"] |
abe05a73 XL |
115 | pub struct Unfold<St, F> { |
116 | f: F, | |
117 | /// Internal state that will be passed to the closure on the next iteration | |
118 | pub state: St, | |
119 | } | |
120 | ||
121 | impl<A, St, F> Iterator for Unfold<St, F> | |
122 | where F: FnMut(&mut St) -> Option<A> | |
123 | { | |
124 | type Item = A; | |
125 | ||
126 | #[inline] | |
127 | fn next(&mut self) -> Option<A> { | |
128 | (self.f)(&mut self.state) | |
129 | } | |
130 | ||
131 | #[inline] | |
132 | fn size_hint(&self) -> (usize, Option<usize>) { | |
133 | // no possible known bounds at this point | |
134 | (0, None) | |
135 | } | |
136 | } | |
137 | ||
138 | /// An iterator that infinitely applies function to value and yields results. | |
139 | /// | |
140 | /// This `struct` is created by the [`iterate()`] function. See its documentation for more. | |
141 | /// | |
142 | /// [`iterate()`]: ../fn.iterate.html | |
143 | #[derive(Clone)] | |
2c00a5a8 | 144 | #[must_use = "iterators are lazy and do nothing unless consumed"] |
abe05a73 XL |
145 | pub struct Iterate<St, F> { |
146 | state: St, | |
147 | f: F, | |
148 | } | |
149 | ||
150 | impl<St, F> fmt::Debug for Iterate<St, F> | |
151 | where St: fmt::Debug, | |
152 | { | |
153 | debug_fmt_fields!(Iterate, state); | |
154 | } | |
155 | ||
156 | impl<St, F> Iterator for Iterate<St, F> | |
157 | where F: FnMut(&St) -> St | |
158 | { | |
159 | type Item = St; | |
160 | ||
161 | #[inline] | |
162 | fn next(&mut self) -> Option<Self::Item> { | |
163 | let next_state = (self.f)(&self.state); | |
164 | Some(mem::replace(&mut self.state, next_state)) | |
165 | } | |
166 | ||
167 | #[inline] | |
168 | fn size_hint(&self) -> (usize, Option<usize>) { | |
169 | (usize::max_value(), None) | |
170 | } | |
171 | } | |
172 | ||
173 | /// Creates a new iterator that infinitely applies function to value and yields results. | |
174 | /// | |
175 | /// ``` | |
176 | /// use itertools::iterate; | |
177 | /// | |
178 | /// itertools::assert_equal(iterate(1, |&i| i * 3).take(5), vec![1, 3, 9, 27, 81]); | |
179 | /// ``` | |
180 | pub fn iterate<St, F>(initial_value: St, f: F) -> Iterate<St, F> | |
181 | where F: FnMut(&St) -> St | |
182 | { | |
183 | Iterate { | |
184 | state: initial_value, | |
185 | f: f, | |
186 | } | |
187 | } |