proto_vulcan/relation/
member.rs

1use crate::engine::Engine;
2use crate::goal::{AnyGoal, InferredGoal};
3use crate::lterm::LTerm;
4use crate::user::User;
5
6/// A relation that succeeds for each occurrence of `x` in list `l`.
7///
8/// # Example
9/// ```rust
10/// extern crate proto_vulcan;
11/// use proto_vulcan::prelude::*;
12/// use proto_vulcan::relation::member;
13/// fn main() {
14///     let query = proto_vulcan_query!(|q| {
15///         member(q, [1, 2, 3])
16///     });
17///     let mut iter = query.run();
18///     assert!(iter.next().unwrap().q == 1);
19///     assert!(iter.next().unwrap().q == 2);
20///     assert!(iter.next().unwrap().q == 3);
21///     assert!(iter.next().is_none());
22/// }
23/// ```
24pub fn member<U, E, G>(x: LTerm<U, E>, l: LTerm<U, E>) -> InferredGoal<U, E, G>
25where
26    U: User,
27    E: Engine<U>,
28    G: AnyGoal<U, E>,
29{
30    proto_vulcan_closure!(match l {
31        [head | _] => head == x,
32        [_ | rest] => member(x, rest),
33    })
34}
35
36#[cfg(test)]
37mod test {
38    use super::*;
39    use crate::prelude::*;
40
41    #[test]
42    fn test_member_1() {
43        let query = proto_vulcan_query!(|q| { member(q, [1, 2, 3]) });
44        let mut iter = query.run();
45        assert!(iter.next().unwrap().q == 1);
46        assert!(iter.next().unwrap().q == 2);
47        assert!(iter.next().unwrap().q == 3);
48        assert!(iter.next().is_none());
49    }
50
51    #[test]
52    fn test_member_2() {
53        let query = proto_vulcan_query!(|q| { member(q, [1, 1, 1]) });
54        let mut iter = query.run();
55        assert!(iter.next().unwrap().q == 1);
56        assert!(iter.next().unwrap().q == 1);
57        assert!(iter.next().unwrap().q == 1);
58        assert!(iter.next().is_none());
59    }
60
61    #[test]
62    fn test_member_3() {
63        let query = proto_vulcan_query!(|q| { member(q, []) });
64        assert!(query.run().next().is_none());
65    }
66}