lazy_seq/
lib.rs

1//! # Lazy Seq
2//!
3//! `lazy_seq` is a crate containing tools for lazily evaluated
4//! collections, specifically Seq which is a collection of lazily
5//! evaluated functions, and Lazy, which is the primitive used for lazy
6//! evaluation.
7
8/// Stores an operation which can be evaluated when required.
9pub struct Lazy<T> {
10    f : Option<Box<dyn FnOnce() -> T>>,
11    val : Option<T>,
12}
13
14impl<T> Lazy<T> {
15    /// Constructs a new `Lazy<T>` from a closure implementing `FnOnce() -> T`. 
16    pub fn new<F : FnOnce() -> T + 'static>(f : F) -> Lazy<T> {
17        Lazy {
18            f : Some(Box::new(f)),
19            val : None, 
20        }
21    }
22
23    /// Forces evaluation of the underlying function.
24    pub fn force(&mut self) {
25        if self.f.is_some() {
26            let mut f = None;
27            std::mem::swap(&mut f, &mut self.f);
28
29            let f = f.unwrap();
30            let result = (f)();
31            self.val = Some(result);
32        }
33    }
34
35    /// Forces evaluation of the underlying function and returns the inside value, consuming
36    /// the `Lazy<T>`.
37    pub fn into_inner(mut self) -> T {
38        self.force();
39        let Lazy { f : _ , val } = self;
40        val.unwrap()
41    }
42
43    /// Returns an immutable reference to the result of the function.
44    pub fn as_ref(&mut self) -> &T {
45        self.force();
46        self.val.as_ref().unwrap()
47    }
48}
49
50impl<T> AsMut<T> for Lazy<T> {
51    /// Returns a mutable reference to the result of the function.
52    fn as_mut(&mut self) -> &mut T {
53        self.force();
54        self.val.as_mut().unwrap()
55    }
56}
57
58impl<T> Default for Lazy<T>
59    where T : Default {
60    fn default() -> Self {
61        Lazy {
62            f : None,
63            val : Some(T::default())
64        }
65    }
66}
67
68/// A lazily evaluated sequence of functions.
69pub struct Seq<T>(Vec<Lazy<T>>);
70
71impl<T> Seq<T> {
72    /// Constructs a new, empty `Seq<T>`.
73    pub fn new() -> Seq<T> {
74        Seq(Vec::new())
75    }
76
77    /// Returns `true` if the sequence contains no elements.
78    pub fn is_empty(&self) -> bool {
79        self.len() == 0
80    }
81
82    // Returns the number of elements the sequence can hold without reallocating.
83    pub fn capacity(&self) -> usize {
84        self.0.capacity()
85    }
86
87    /// Returns the number of elements in the sequence, also referred to as its ‘length’.
88    pub fn len(&self) -> usize {
89        self.0.len()
90    }
91
92    /// Constructs a new, empty `Seq<T>` with the specified capacity.
93    pub fn with_capacity(capacity : usize) -> Seq<T> {
94        Seq(Vec::with_capacity(capacity))
95    }
96
97    /// Appends the provided function to the back of the collection.
98    pub fn push<F : FnOnce() -> T + 'static>(&mut self, value : F) {
99        self.0.push(Lazy::new(value))
100    }
101
102    /// Forces evaluation of the last function in the sequence, returning the result.
103    pub fn pop(&mut self) -> Option<T> {
104        let lazy = self.0.pop();
105        lazy.map(|l| l.into_inner())
106    }
107
108    /// Evaluates all unevaluated functions within the Seq.
109    pub fn force_all(&mut self) {
110        for i in 0..self.0.len() {
111            self.0[i].force()
112        }
113    }
114
115    /// Converts a `Seq<T>` to a `Vec<T>` by forcing evaluation of all functions.
116    pub fn to_vec(self) -> Vec<T> {
117        let Seq(vec) = self;
118
119        vec
120        .into_iter()
121        .map(|x| x.into_inner())
122        .collect()
123    }
124
125    /// Converts a `Seq<T>` to a `Vec<Lazy<T>>` without evaluating any additional
126    /// functions.
127    pub fn to_lazy_vec(self) -> Vec<Lazy<T>> {
128        let Seq(vec) = self;
129        vec
130    }
131
132    /// Gets an immutable reference to the value at the specified index.
133    pub fn get(&mut self, index : usize) -> Option<&T> {
134        self.0.get_mut(index).map(|l| { l.force(); l.as_ref() })
135    }
136
137    /// Gets a mutable reference to the value at the specified index.
138    pub fn get_mut(&mut self, index : usize) -> Option<&mut T> {
139        self.0.get_mut(index).map(|l| { l.force(); l.as_mut() })
140    }
141}
142
143impl<T> From<Vec<Box<dyn FnOnce() -> T>>> for Seq<T> {
144    fn from(vec : Vec<Box<dyn FnOnce() -> T>>) -> Self {
145        Seq(
146            vec
147            .into_iter()
148            .map(|b| Lazy { f : Some(b), val : None })
149            .collect()
150        )
151    }
152}
153
154impl<T> From<Vec<T>> for Seq<T> {
155    fn from(vec : Vec<T>) -> Self {
156        Seq(
157            vec
158            .into_iter()
159            .map(|v| Lazy { f : None, val : Some(v) })
160            .collect()
161        )
162    }
163}
164
165impl<T> Default for Seq<T> {
166    fn default() -> Self {
167        Self::new()
168    }
169}
170
171/// Constructs a Seq from a literal in a similar way that vec! does for Vec.
172#[macro_export]
173macro_rules! seq {
174    () => (
175        lazy_seq::Seq::new()
176    );
177    ($elem:expr; $n:expr) => (
178        {
179            let mut seq = Seq::with_capacity($n);
180            for _ in 0..$n {
181                seq.push($elem);
182            }
183            seq
184        }
185    );
186    ($($x:expr),+ $(,)?) => (
187        {
188            let mut seq = Seq::new();
189            $(seq.push($x);)*
190            seq
191        }
192    );
193}
194
195#[cfg(test)]
196mod tests {
197    use std::rc::Rc;
198    use std::cell::RefCell;
199    use crate::{Lazy, Seq, seq};
200    #[test]
201    pub fn lazy_correct() {
202        let counter = Rc::new(RefCell::new(0));
203        let counter_new = counter.clone();
204        let mut lazy = Lazy::new(
205            move || {
206                *counter_new.borrow_mut() += 1;
207                5 + 5
208            });
209        let result = lazy.as_ref();
210        assert_eq!(10, *result);
211    }
212
213    #[test]
214    pub fn seq_correct() {
215
216        let counter = Rc::new(RefCell::new(0));
217        let counter_new = counter.clone();
218
219        let mut seq = seq![
220            || { 0 }; 9
221        ];
222
223        assert_eq!(9, seq.len());
224
225        seq.push(move || {
226            *counter_new.borrow_mut() += 1;
227            println!("{:?}", counter_new);
228            5 + 5
229        });
230
231        assert_eq!(10, seq.len());
232
233        assert_eq!(0, *counter.borrow());
234
235        let _ = seq.get(9).unwrap();
236
237        assert_eq!(1, *counter.borrow());
238
239        seq.force_all();
240        let result = seq.pop();
241        assert_eq!(9, seq.len());
242        assert_eq!(1, *counter.borrow());
243        assert_eq!(10, result.unwrap());
244    }
245}