canrun 0.2.0

A logic programming library inspired by the *Kanren family of language DSLs.
Documentation
use super::super::state::{Fork, IterResolved, State};
use crate::domains::Domain;
use crate::example::I32;
use crate::value::val;
use std::fmt;
use std::rc::Rc;

struct Either<'a, D: Domain<'a>>(
    Rc<dyn Fn(State<'a, D>) -> Option<State<'a, D>> + 'a>,
    Rc<dyn Fn(State<'a, D>) -> Option<State<'a, D>> + 'a>,
);

impl<'a, D: Domain<'a>> fmt::Debug for Either<'a, D> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "Either")
    }
}

impl<'a, D> Fork<'a, D> for Either<'a, D>
where
    D: Domain<'a>,
{
    fn fork(&self, state: State<'a, D>) -> crate::state::StateIter<'a, D> {
        let a = (self.0)(state.clone()).into_iter();
        let b = (self.1)(state).into_iter();
        Box::new(a.chain(b))
    }
}

#[test]
fn basic_fork_first_success() {
    let state: State<I32> = State::new();
    let state = state.fork(Rc::new(Either(
        Rc::new(|s| s.unify(&val!(2), &val!(2))),
        Rc::new(|s| s.unify(&val!(1), &val!(2))),
    )));
    let results: Vec<_> = state.unwrap().iter_resolved().collect();
    assert_eq!(1, results.len());
}

#[test]
fn basic_fork_second_success() {
    let state: State<I32> = State::new();
    let state = state.fork(Rc::new(Either(
        Rc::new(|s| s.unify(&val!(1), &val!(2))),
        Rc::new(|s| s.unify(&val!(2), &val!(2))),
    )));
    assert_eq!(1, state.iter_resolved().count());
}

#[test]
fn basic_fork_both_success() {
    let state: State<I32> = State::new();
    let state = state.fork(Rc::new(Either(
        Rc::new(|s| s.unify(&val!(1), &val!(1))),
        Rc::new(|s| s.unify(&val!(2), &val!(2))),
    )));
    assert_eq!(2, state.iter_resolved().count());
}