canrun/core/
query.rs

1use super::{Reify, StateIterator};
2
3/**
4Derive [reified](crate::core::Reify) [values](crate::Value) potential
5resolved states.
6
7[Query] is implemented for [`Goals`](crate::goals) and
8[`States`](crate::State), meaning you can call
9[`.query()`](Query::query()) on them with any type that implements
10[`Reify`].
11
12This is a convenient wrapper around the common pattern of obtaining a
13[`StateIter`](crate::core::StateIter), making sure each resulting state is
14[`.ready()`](crate::State::ready), and calling
15[`.reify(query)`](crate::core::ReadyState::reify()) to return only the
16valid, fully resolved results. Query is implemented on a variety of
17[`State`](crate::State) related types, allowing it to be used in many
18contexts.
19
20If a state is not ready (meaning it has open forks and/or constraints still
21waiting for variables to be resolved) it will not be returned by the query.
22
23A blanket impl covers anything that implements [`StateIterator`], so many
24types including [`Goal`](crate::goals) and [`State`](crate::State) are
25queryable.
26*/
27pub trait Query<'a> {
28    /**
29    Get [reified](crate::core::Reify) results from things that can produce
30    [`StateIter`](crate::core::StateIter)s.
31
32    This will call [`State::ready()`](crate::State::ready) internally, so results will not be returned
33    from states with unresolved constraints.
34
35    # Examples:
36
37    ## Goals
38    ```
39    use canrun::{Query, LVar};
40    use canrun::goals::unify;
41
42    let x = LVar::new();
43    let goal = unify(x, 1);
44    let result: Vec<_> = goal.query(x).collect();
45    assert_eq!(result, vec![1])
46    ```
47
48    ### `State` and `Option<State>`
49    Most of the lower level [`State`](crate::State) update methods
50    return an `Option<State>`. Since [`StateIterator`] is implemented for
51    this type, Query is as well!
52    ```
53    # use canrun::{State, StateIterator, Query, Value};
54    # let x = Value::var();
55    let state: Option<State> = State::new().unify(&x, &Value::new(1));
56    let result: Vec<_> = state.query(x).collect();
57    assert_eq!(result, vec![1])
58    ```
59    */
60    fn query<Q: Reify + 'a>(self, query: Q) -> Box<dyn Iterator<Item = Q::Reified> + 'a>;
61}
62
63impl<'a, S: StateIterator + 'a> Query<'a> for S {
64    fn query<Q: Reify + 'a>(self, query: Q) -> Box<dyn Iterator<Item = Q::Reified> + 'a> {
65        Box::new(
66            self.into_states()
67                .filter_map(move |s| query.reify_in(&s.ready()?)),
68        )
69    }
70}