itertools_wild/special/mod.rs
1
2use std::cell::Cell;
3
4mod inner {
5 use std::cell::Cell;
6
7 pub struct Inner<'a, T: 'a>(pub &'a Cell<Option<T>>);
8
9 impl<'a, T: Copy> Iterator for Inner<'a, T> {
10 type Item = T;
11
12 fn next(&mut self) -> Option<T> {
13 self.0.get()
14 }
15 }
16}
17
18/// Self-referential iterator adaptor builder
19///
20/// See `feedback` for more information.
21pub struct Feedback<T> {
22 t: Cell<Option<T>>,
23}
24
25/// Self-referential iterator adaptor
26///
27/// See `feedback` for more information.
28pub struct FeedbackIter<'a, I, T: 'a> {
29 iter: I,
30 inner: &'a Cell<Option<T>>,
31}
32
33/**
34 * Feed the output of an iterator pipeline back to the input. Feedback
35 * is delayed by one timestep to preserve causality, so the first input
36 * is provided by `initial`, and the output of that pass is used as the
37 * input for the second pass, and so on.
38 *
39 * Every time the input is requested, it yields the last result returned
40 * by the pipeline. The pipeline can request the feedback value any
41 * number of times per cycle, including ignoring it entirely. If the
42 * pipeline doesn't request a particular input, that input is discarded,
43 * not saved for the next cycle. If the pipeline requests an input
44 * multiple times in the process of producing an output, the same input
45 * will be returned each time.
46 *
47 * ```rust
48 * use itertools_wild::special::feedback;
49 *
50 * let input = [1, -2, 3, -4, 5];
51 * let result: Vec<i32> = feedback(0).feed(|feedback|
52 * feedback.zip(&input)
53 * .map(|(a, b)| a + b)
54 * ).collect();
55 * assert_eq!(result, &[0, 1, -1, 2, -2, 3]);
56 * ```
57 */
58pub fn feedback<T>(initial: T) -> Feedback<T>
59 where T: Copy
60{
61 Feedback {
62 t: Cell::new(Some(initial)),
63 }
64}
65
66
67impl<T> Feedback<T> where T: Copy
68{
69 pub fn feed<'a, F, I>(&'a mut self, inner: F) -> FeedbackIter<'a, I, T>
70 where F: FnOnce(inner::Inner<'a, T>) -> I,
71 T: Copy
72 {
73 FeedbackIter {
74 iter: inner(inner::Inner(&self.t)),
75 inner: &self.t,
76 }
77 }
78}
79
80impl<'a, I, T> Iterator for FeedbackIter<'a, I, T>
81 where I: Iterator<Item = T>,
82 T: Copy
83{
84 type Item = T;
85
86 fn next(&mut self) -> Option<T> {
87 if let Some(v) = self.inner.get() {
88 self.inner.set(self.iter.next());
89 Some(v)
90 } else {
91 None
92 }
93 }
94}