evobench_tools/utillib/
conslist.rs

1//! Cons list. Only works with normal references. That's because
2//! making it generic for the reference/container type appears
3//! unworkable, even though feasible in principle, due to requiring
4//! explicit type parameters on every single cons call. The solution
5//! will be to generate the code for versions using Rc, Arc or
6//! whatever when needed. (Or, use dyn?, or perhaps/probably rather,
7//! enum.)
8
9pub enum List<'t, T> {
10    Pair(T, &'t List<'t, T>),
11    Null,
12}
13
14impl<'t, T> List<'t, T> {
15    pub fn len(&self) -> usize {
16        match self {
17            List::Pair(_, r) => r.len() + 1,
18            List::Null => 0,
19        }
20    }
21
22    pub fn is_empty(&self) -> bool {
23        match self {
24            List::Pair(_, _) => false,
25            List::Null => true,
26        }
27    }
28
29    pub fn first(&self) -> Option<&T> {
30        match self {
31            List::Pair(v, _) => Some(v),
32            List::Null => None,
33        }
34    }
35
36    pub fn rest<'s>(&'s self) -> Option<&'s List<'s, T>> {
37        match self {
38            List::Pair(_, r) => Some(r),
39            List::Null => None,
40        }
41    }
42
43    pub fn last(&self) -> Option<&T> {
44        match self {
45            List::Pair(v, List::Null) => Some(v),
46            List::Pair(_, r) => r.last(),
47            List::Null => None,
48        }
49    }
50
51    /// A Vec of all the values as references.
52    // For reverse simply reverse the Vec afterwards yourself? (Could
53    // also get length then fill in unsafely or require Default.)
54    pub fn as_ref_vec(&self) -> Vec<&T> {
55        let mut vs = Vec::new();
56        let mut r = self;
57        while let List::Pair(v, r2) = r {
58            vs.push(v);
59            r = r2;
60        }
61        vs
62    }
63
64    pub fn to_vec(&self) -> Vec<T>
65    where
66        T: Clone,
67    {
68        let mut vs: Vec<T> = Vec::new();
69        let mut r = self;
70        while let List::Pair(v, r2) = r {
71            vs.push(v.clone());
72            r = r2;
73        }
74        vs
75    }
76
77    pub fn any(&self, mut f: impl FnMut(&T) -> bool) -> bool {
78        let mut vs = self;
79        loop {
80            match vs {
81                List::Pair(val, list) => {
82                    if f(val) {
83                        return true;
84                    }
85                    vs = list;
86                }
87                List::Null => return false,
88            }
89        }
90    }
91}
92
93pub fn cons<'l, T>(v: T, r: &'l List<T>) -> List<'l, T> {
94    List::Pair(v, r)
95}
96
97#[cfg(test)]
98mod tests {
99    use super::*;
100
101    #[test]
102    fn t_() {
103        let a = List::Pair(5, &List::Null);
104        let b = List::Pair(7, &a);
105        let c = List::Pair(9, &b);
106        let d = cons(13, &b);
107        let e = cons(14, &c);
108        assert_eq!(List::Null::<i8>.as_ref_vec(), Vec::<&i8>::new());
109        assert_eq!(a.to_vec(), vec![5]);
110        assert_eq!(b.as_ref_vec(), vec![&7, &5]);
111        assert_eq!(c.rest().unwrap().to_vec(), vec![7, 5]);
112        assert_eq!(c.to_vec(), vec![9, 7, 5]);
113        assert_eq!(d.to_vec(), vec![13, 7, 5]);
114        assert_eq!(e.to_vec(), vec![14, 9, 7, 5]);
115    }
116}