assert-rs / predicates-rs

Boolean-valued predicate functions in Rust
docs.rs/predicates
Apache License 2.0
173 stars 29 forks source link

Predicates for tuple.n #96

Open noriapi opened 3 years ago

noriapi commented 3 years ago

Something like this.

use predicates::reflection;
use predicates::Predicate;
use std::fmt;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Tuple0<T>(T);

fn tuple0<T>(inner: T) -> Tuple0<T> {
    Tuple0(inner)
}

impl<T: fmt::Display> fmt::Display for Tuple0<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{{let var = var.0; {}}}", self.0)
    }
}

impl<T: fmt::Display> reflection::PredicateReflection for Tuple0<T> {}

impl<T0, U0> Predicate<(U0,)> for Tuple0<T0>
where
    T0: fmt::Display + Predicate<U0>,
{
    fn eval(&self, variable: &(U0,)) -> bool {
        self.0.eval(&variable.0)
    }
}

impl<T, U, U1> Predicate<(U, U1)> for Tuple0<T>
where
    T: fmt::Display + Predicate<U>,
{
    fn eval(&self, variable: &(U, U1)) -> bool {
        self.0.eval(&variable.0)
    }
}

// impl<T, U, U1, U2> Predicate<(U, U1, U2)> for Tuple0<T>
// impl<T, U, U1, U2, U3> Predicate<(U, U1, U2, U3)> for Tuple0<T>
// ...

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Tuple1<T>(T);

fn tuple1<T>(inner: T) -> Tuple1<T> {
    Tuple1(inner)
}

impl<T: fmt::Display> fmt::Display for Tuple1<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{{let var = var.1; {}}}", self.0)
    }
}

impl<T: fmt::Display> reflection::PredicateReflection for Tuple1<T> {}

impl<T, U0, U> Predicate<(U0, U)> for Tuple1<T>
where
    T: fmt::Display + Predicate<U>,
{
    fn eval(&self, variable: &(U0, U)) -> bool {
        self.0.eval(&variable.1)
    }
}

// impl<T, U0, U, U2> Predicate<(U0, U, U2)> for Tuple1<T>
// impl<T, U0, U, U2, U3> Predicate<(U0, U, U2, U3)> for Tuple1<T>
// ...

fn main() {
    use predicates::prelude::*;

    let t1 = (0,);
    let t2 = (0, 1);

    let p0 = tuple0(predicates::ord::eq(0));
    let p1 = tuple1(predicates::ord::eq(2));

    assert_eq!(p0.eval(&t1), true);
    assert_eq!(p0.eval(&t2), true);
    assert_eq!(p1.eval(&t2), false);
    assert_eq!(p0.and(p1).eval(&t2), false);
    assert_eq!(p0.or(p1).eval(&t2), true);
}
epage commented 3 years ago

Wish we could use const-generics for indexing into a tuple.

The main question I can think of is how many tuple positions should we support?

noriapi commented 3 years ago

Wish we could use const-generics for indexing into a tuple.

Yes, I agree.

The main question I can think of is how many tuple positions should we support?

Std common traits (like Debug PartialEq Clone...) are only implemented on tuples of arity 12 or less. So, I think 12 would be enough.