[][src]Struct canrun::state::State

pub struct State<'a, D: Domain<'a> + 'a> { /* fields omitted */ }

The core struct used to contain and manage value bindings.

An open State can be updated in a few different ways. Most update methods return an Option<State<D>> to reflect the fact each new constraint invalidate the state. This gives you the ability to quickly short circuit as soon the state hits a dead end.

In general, it is most ergonomic to manipulate a state inside a function that returns an Option<State<D>> to allow the use of the question mark operator (Note that the .apply() function makes it easy to do this).

use canrun::{State, val, var};
use canrun::domains::example::I32;

fn my_fn<'a>() -> Option<State<'a, I32>> {
    let x = var();
    let y = var();
    let state: State<I32> = State::new();
    let maybe: Option<State<I32>> = state.unify(&val!(x), &val!(1));
    maybe?.unify(&val!(x), &val!(y))
}
assert!(my_fn().is_some());

Implementations

impl<'a, D: Domain<'a> + 'a> State<'a, D>[src]

pub fn new() -> Self[src]

Create a new, empty state.

This often does not need to be used directly as you can .query() a Goal directly, which handles the state creation internally.

However, there are use cases for creating and managing a state independently of any goals.

Example:

use canrun::{State, var};
use canrun::domains::example::I32;

let state: State<I32> = State::new();

pub fn apply<F>(self, func: F) -> Option<Self> where
    F: Fn(Self) -> Option<Self>, 
[src]

Apply an arbitrary function to a state.

This is primarily a helper to make it easier to get into a function where you can use the question mark operator while applying multiple updates to a state.

Example:

use canrun::{State, Query, val, var};
use canrun::domains::example::I32;

let s: State<I32> = State::new();
let x = var();
let s = s.apply(|s| {
    s.unify(&val!(x), &val!(1))?
     .unify(&val!(1), &val!(x))
});
let results: Vec<i32> = s.query(x).collect();
assert_eq!(results, vec![1]);

pub fn resolve_val<'r, T>(&'r self, val: &'r Val<T>) -> &'r Val<T> where
    T: Debug,
    D: DomainType<'a, T>, 
[src]

Recursively resolve a Val as far as the currently known variable bindings allow.

This will return either the final Val::Resolved (if found) or the last Val::Var it attempted to resolve. It will not force forks to enumerate, so potential bindings are not considered.

Example:

use canrun::{State, Query, val, var};
use canrun::domains::example::I32;

let state: State<I32> = State::new();

let x = val!(var());
assert_eq!(state.resolve_val(&x), &x);

let state = state.unify(&x, &val!(1))?;
assert_eq!(state.resolve_val(&x), &val!(1));

pub fn unify<T>(self, a: &Val<T>, b: &Val<T>) -> Option<Self> where
    T: UnifyIn<'a, D> + Debug,
    D: DomainType<'a, T>, 
[src]

Attempt to unify two values with each other.

If the unification fails, None will be returned. Val::Vars will be checked against relevant constraints, which can also cause a state to fail.

Examples:

use canrun::{State, Query, val, var};
use canrun::domains::example::I32;

let x = val!(var());

let state: State<I32> = State::new();
let state = state.unify(&x, &val!(1));
assert!(state.is_some());
let state: State<I32> = State::new();
let state = state.unify(&val!(1), &val!(2));
assert!(state.is_none());

pub fn constrain(
    self,
    constraint: Rc<dyn Constraint<'a, D> + 'a>
) -> Option<Self>
[src]

Add a constraint to the store that can be reevaluated as variables are resolved.

Some logic is not easy or even possible to express until the resolved values are available. .constrain() provides a low level way to run custom imperative code whenever certain bindings are updated.

See the Constraint trait for more information.

pub fn fork(self, fork: Rc<dyn Fork<'a, D> + 'a>) -> Option<Self>[src]

Add a potential fork point to the state.

If there are many possibilities for a certain value or set of values, this method allows you to add a Fork object that can enumerate those possible alternate states.

While this is not quite as finicky as the Constraints, you still probably want to use the any or either goals.

Unification is performed eagerly as soon as it is called. Constraints are run as variables are resolved. Forking is executed lazily at the end, when .iter_resolved() (or `.query()) is called.

Trait Implementations

impl<'a, D: Clone + Domain<'a> + 'a> Clone for State<'a, D>[src]

impl<'a, D: Domain<'a> + 'a> Debug for State<'a, D>[src]

impl<'a, D: Domain<'a>> Default for State<'a, D>[src]

impl<'a, D: Domain<'a> + 'a> IterResolved<'a, D> for State<'a, D>[src]

Auto Trait Implementations

impl<'a, D> !RefUnwindSafe for State<'a, D>

impl<'a, D> !Send for State<'a, D>

impl<'a, D> !Sync for State<'a, D>

impl<'a, D> Unpin for State<'a, D> where
    D: Unpin

impl<'a, D> !UnwindSafe for State<'a, D>

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Same<T> for T

type Output = T

Should always be Self

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

impl<V, T> VZip<V> for T where
    V: MultiLane<T>,