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}