canrun/collections/lvec/
mod.rs

1//! A [`Vec`]-like data structure with [`Value`](crate::Value) values.
2
3mod get;
4mod member;
5mod slice;
6mod subset;
7
8use crate::{
9    core::{Reify, State, Unify, Value},
10    ReadyState,
11};
12pub use get::{get, Get};
13pub use member::{member, Member};
14pub use slice::{slice, Slice};
15pub use subset::{subset, Subset};
16
17use std::rc::Rc;
18
19/// A [`Vec`]-like data structure with [`Value`](crate::Value) values.
20///
21/// Construct with the [`lvec!`](crate::lvec!) macro, or you can use the
22/// `From<Vec<Value<T>>>` or `FromIterator<Value<T>>` trait implementations.
23#[derive(Debug)]
24pub struct LVec<T: Unify> {
25    vec: Vec<Value<T>>,
26}
27
28impl<T: Unify> LVec<T> {
29    /// Returns the number of elements in the [`LVec`].
30    pub fn len(&self) -> usize {
31        self.vec.len()
32    }
33
34    /// Returns true if the [`LVec`] contains no elements.
35
36    pub fn is_empty(&self) -> bool {
37        self.vec.is_empty()
38    }
39}
40
41/** Create an [`LVec<T>`](crate::collections::lvec::LVec) with automatic `Into<Value<T>>` conversion.
42
43The primary benefit is that it allows freely mixing `T`, [`Value<T>`](crate::Value) and
44[`LVar<T>`](crate::LVar) without needing to do manual conversion.
45*/
46#[macro_export]
47macro_rules! lvec {
48    ($($item:expr),* $(,)?) => {
49        {
50            let vec = vec![$($item.into(),)*];
51            $crate::collections::lvec::LVec::from(vec)
52        }
53    };
54}
55
56impl<T: Unify> Unify for LVec<T> {
57    fn unify(state: State, a: Rc<Self>, b: Rc<Self>) -> Option<State> {
58        if a.vec.len() == b.vec.len() {
59            a.vec
60                .iter()
61                .zip(b.vec.iter())
62                .try_fold(state, |s: State, (a, b)| s.unify(a, b))
63        } else {
64            None
65        }
66    }
67}
68
69impl<T: Unify + Reify> Reify for LVec<T> {
70    type Reified = Vec<T::Reified>;
71    fn reify_in(&self, state: &ReadyState) -> Option<Vec<T::Reified>> {
72        self.vec
73            .iter()
74            .map(|v: &Value<T>| v.reify_in(state))
75            .collect()
76    }
77}
78
79impl<T: Unify> From<Vec<Value<T>>> for LVec<T> {
80    fn from(vec: Vec<Value<T>>) -> Self {
81        LVec { vec }
82    }
83}
84
85impl<T: Unify> From<&[Value<T>]> for LVec<T> {
86    fn from(slice: &[Value<T>]) -> Self {
87        LVec {
88            vec: slice.to_vec(),
89        }
90    }
91}
92
93impl<T: Unify> FromIterator<Value<T>> for LVec<T> {
94    fn from_iter<I: IntoIterator<Item = Value<T>>>(iter: I) -> Self {
95        LVec {
96            vec: iter.into_iter().collect(),
97        }
98    }
99}
100
101impl<T: Unify> FromIterator<T> for LVec<T> {
102    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
103        LVec {
104            vec: iter.into_iter().map(Value::new).collect(),
105        }
106    }
107}
108
109#[cfg(test)]
110mod tests {
111    use crate::{core::LVar, core::Query, goals::unify, lvec::LVec, Value};
112
113    #[test]
114    fn succeeds() {
115        let x = LVar::new();
116        let goal = unify(lvec![x, 2], lvec![1, 2]);
117        assert_eq!(goal.query(x).collect::<Vec<_>>(), vec![1]);
118    }
119
120    #[test]
121    fn fails() {
122        let x = LVar::new();
123        let goal = unify(lvec![x, 1], lvec![1, 2]);
124        assert_eq!(goal.query(x).count(), 0);
125    }
126
127    #[test]
128    fn is_empty() {
129        let empty: LVec<usize> = lvec![];
130        assert!(empty.is_empty());
131    }
132
133    #[test]
134    fn from_iter_value_t() {
135        let from_iter: LVec<usize> = (1..3).collect();
136        assert_eq!(from_iter.vec, vec![Value::new(1), Value::new(2)]);
137    }
138
139    #[test]
140    fn from_iter_t() {
141        let from_iter: LVec<usize> = (1..3).map(Value::new).collect();
142        assert_eq!(from_iter.vec, vec![Value::new(1), Value::new(2)]);
143    }
144}