canrun 0.2.0

A logic programming library inspired by the *Kanren family of language DSLs.
Documentation
use canrun::example::I32;
use canrun::{all, any, either, unify, var, Goal};
use criterion::Criterion;

macro_rules! goal_bench {
    ($c:ident $name:literal ($($v:ident),+) $goal:block) => {
        $c.bench_function(&format!("{} goal", $name), |b| {
            $(let $v = var();)+
            b.iter(|| $goal);
        });

        $c.bench_function(&format!("{} query", $name), |b| {
            $(let $v = var();)+
            b.iter(|| $goal.query(($($v),+)));
        });

        $c.bench_function(&format!("{} nth(0)", $name), |b| {
            $(let $v = var();)+
            b.iter(|| {
                $goal.query(($($v),+)).nth(0)
            });
        });

        $c.bench_function(&format!("{} collect()", $name), |b| {
            $(let $v = var();)+
            b.iter(|| {
                let results: Vec<_> = $goal.query(($($v),+)).collect();
                results
            });
        });
    }
}

pub fn benches(c: &mut Criterion) {
    goal_bench! {c "one" (x) {
        unify(x, 1) as Goal<I32>
    }}

    goal_bench! {c "two" (x, y) {
        all![unify(x, 1), unify(y, 1), unify(y, x)] as Goal<I32>
    }}

    goal_bench! {c "three" (x, y, z) {
        all![
            unify(x, 1),
            unify(y, 1),
            unify(z, 1),
            unify(y, x),
            unify(x, z),
        ] as Goal<I32>
    }}

    goal_bench! {c "forking" (a, b, c, d, e) {
        all![
            unify(a, 1),
            unify(b, 1),
            unify(c, 1),
            unify(b, a),
            unify(a, c),
            either(unify(d, c), unify(d, e)),
            unify(e, 2),
            either(unify(d, e), unify(a, e)),
        ] as Goal<I32>
    }}

    goal_bench! {c "fail_after_forking" (a, b, c, d, e) {
        all![
            unify(a, 1),
            unify(b, 1),
            unify(c, 1),
            unify(b, a),
            unify(a, c),
            either(unify(d, c), unify(d, e)),
            unify(e, 2),
            either(unify(a, 2), unify(b, 3)),
        ] as Goal<I32>
    }}

    goal_bench! {c "fail_before_forking" (a, b, c, d, e) {
        all![
            unify(a, 1),
            unify(b, 1),
            unify(c, 1),
            unify(b, a),
            unify(a, c),
            either(unify(d, c), unify(d, e)),
            unify(e, 2),
            unify(e, a),
            either(unify(d, e), unify(a, e)),
        ] as Goal<I32>
    }}

    goal_bench! {c "unify_a_chain" (k) {
        {
            let (a, b, c, d, e, f, g, h, i, j) =
                (var(), var(), var(), var(), var(), var(), var(), var(), var(), var());
            all![
                unify(1, a),
                unify(a, b),
                unify(b, c),
                unify(c, d),
                unify(d, e),
                unify(e, f),
                unify(f, g),
                unify(g, h),
                unify(h, i),
                unify(i, j),
                unify(j, k),
            ] as Goal<I32>
        }
    }}

    goal_bench! {c "unify_a_repetitive" (k) {
        {
            let (a, b, c, d, e, f, g, h, i, j) =
                (var(), var(), var(), var(), var(), var(), var(), var(), var(), var());
            all![
                unify(a, 1),
                unify(b, 1),
                unify(c, 1),
                unify(d, 1),
                unify(e, 1),
                unify(f, 1),
                unify(g, 1),
                unify(h, 1),
                unify(i, 1),
                unify(j, 1),
                unify(k, 1),
            ] as Goal<I32>
        }
    }}

    goal_bench! {c "wide_forking" (a) {
        any![
            unify(a, 1),
            unify(a, 2),
            unify(a, 3),
            unify(a, 4),
            unify(a, 5),
            unify(a, 6),
            unify(a, 7),
            unify(a, 8),
            unify(a, 9),
            unify(a, 10),
            unify(a, 11),
        ] as Goal<I32>
    }}
}