pub trait Constraint {
    fn attempt(&self, state: &State) -> Result<ResolveFn, VarWatch>;
}
Expand description

Update a State whenever one or more LVars are resolved.

The Constraint::attempt function will be run when it is initially added. Returning a Err([VarWatch]) signals that the constraint is not satisfied. The constraint will be re-attempted when one of the specified variables is bound to another value.

You probably want to use the higher level goal projection functions.

NOTE:

The attempt function must take care to fully resolve any variables before creating a VarWatch. The resolve_1, resolve_2, OneOfTwo and TwoOfThree helpers can simplify handling this (plus returning the VarWatch).

Example:

use canrun::{State, Unify, Query, Value};
use canrun::constraints::{Constraint, resolve_1, ResolveFn, VarWatch};
use std::rc::Rc;

struct Assert<T: Unify> {
    val: Value<T>,
    assert: Rc<dyn Fn(&T) -> bool>,
}

impl<T: Unify> Constraint for Assert<T>
{
    fn attempt(&self, state: &State) -> Result<ResolveFn, VarWatch> {
        let resolved = resolve_1(&self.val, state)?;
        let assert = self.assert.clone();
        Ok(Box::new(
            move |state: State| if assert(&*resolved) { Some(state) } else { None },
        ))
    }
}

let x = Value::var();

let state = State::new();
let state = state.constrain(Rc::new(Assert {val: x.clone(), assert: Rc::new(|x| x > &1)}));
let state = state?.unify(&x, &Value::new(2));

let results: Vec<i32> = state.query(x).collect();
assert_eq!(results, vec![2]);

Required Methods§

Resolve required variables in a state and resubscribe or request to update the state.

Implementors§