pub struct Predicate<A> { /* private fields */ }Expand description
An intensional set, defined by a predicate function.
A Predicate<A> wraps a function that determines whether a value of type A
satisfies some condition. Predicates can be combined using logical operations
like AND, OR, NOT, and difference.
Implementations§
Source§impl<A> Predicate<A>
impl<A> Predicate<A>
Sourcepub fn new<F>(f: F) -> Self
pub fn new<F>(f: F) -> Self
Create a new predicate from a closure.
§Parameters
f: A function that evaluates whether a value of typeAsatisfies the predicate.
§Returns
A new Predicate<A> wrapping the provided function.
§Example
use rustica::datatypes::wrapper::predicate::Predicate;
let is_even = Predicate::new(|x: &i32| *x % 2 == 0);
assert!(is_even.contains(&2));
assert!(!is_even.contains(&3));§Performance
- Time Complexity: O(1) - Simply wraps the function in an Rc
- Memory Usage: O(1) - Stores a single Rc pointer to the function
Sourcepub fn contains(&self, a: &A) -> bool
pub fn contains(&self, a: &A) -> bool
Returns true if the value satisfies the predicate.
§Arguments
a- The value to test against the predicate
§Returns
true if the value satisfies the predicate; false otherwise.
§Examples
use rustica::datatypes::wrapper::predicate::Predicate;
let is_positive = Predicate::new(|x: &i32| *x > 0);
assert!(is_positive.contains(&5));
assert!(!is_positive.contains(&-3));§Performance
- Time Complexity: O(f) where f is the complexity of the wrapped function
- Memory Usage: O(1) - No additional memory allocated during evaluation
Sourcepub fn union(&self, other: &Predicate<A>) -> Predicate<A>where
A: 'static,
pub fn union(&self, other: &Predicate<A>) -> Predicate<A>where
A: 'static,
Returns a predicate which is the union of this predicate and another.
The union predicate evaluates to true if either this predicate or the other predicate
evaluates to true for a given input.
§Arguments
other- Another predicate to union with this one
§Returns
A new Predicate<A> representing the union of both predicates
§Examples
use rustica::datatypes::wrapper::predicate::Predicate;
let is_even = Predicate::new(|x: &i32| *x % 2 == 0);
let is_positive = Predicate::new(|x: &i32| *x > 0);
let even_or_positive = is_even.union(&is_positive);
assert!(even_or_positive.contains(&2)); // Even and positive
assert!(even_or_positive.contains(&-4)); // Even but not positive
assert!(even_or_positive.contains(&3)); // Positive but not even
assert!(!even_or_positive.contains(&-5)); // Neither even nor positive§Performance
- Time Complexity: O(1) for creation, O(f1 + f2) for evaluation where f1 and f2 are the complexities of the component predicates
- Memory Usage: O(1) - Creates a new predicate with references to existing ones
- Short-circuit Evaluation: Returns early if the first predicate evaluates to true
Sourcepub fn intersection(&self, other: &Predicate<A>) -> Predicate<A>where
A: 'static,
pub fn intersection(&self, other: &Predicate<A>) -> Predicate<A>where
A: 'static,
Returns a predicate which is the intersection of this predicate and another.
The intersection predicate evaluates to true only if both this predicate and the other predicate
evaluate to true for a given input.
§Arguments
other- Another predicate to intersect with this one
§Returns
A new Predicate<A> representing the intersection of both predicates
§Examples
use rustica::datatypes::wrapper::predicate::Predicate;
let is_even = Predicate::new(|x: &i32| *x % 2 == 0);
let is_positive = Predicate::new(|x: &i32| *x > 0);
let even_and_positive = is_even.intersection(&is_positive);
assert!(even_and_positive.contains(&2)); // Even and positive
assert!(!even_and_positive.contains(&-4)); // Even but not positive
assert!(!even_and_positive.contains(&3)); // Positive but not even
assert!(!even_and_positive.contains(&-5)); // Neither even nor positive§Performance
- Time Complexity: O(1) for creation, O(f1 + f2) for evaluation where f1 and f2 are the complexities of the component predicates
- Memory Usage: O(1) - Creates a new predicate with references to existing ones
- Short-circuit Evaluation: Returns early if the first predicate evaluates to false
Sourcepub fn diff(&self, remove: &Predicate<A>) -> Predicate<A>where
A: 'static,
pub fn diff(&self, remove: &Predicate<A>) -> Predicate<A>where
A: 'static,
Returns a predicate which is the set difference of this predicate and another.
The resulting predicate evaluates to true for inputs that satisfy this predicate
but do not satisfy the remove predicate.
§Arguments
remove- The predicate to subtract from this one
§Returns
A new Predicate<A> representing the set difference
§Examples
use rustica::datatypes::wrapper::predicate::Predicate;
let is_integer = Predicate::new(|x: &f64| x.fract() == 0.0);
let is_negative = Predicate::new(|x: &f64| *x < 0.0);
let positive_integers = is_integer.diff(&is_negative);
assert!(positive_integers.contains(&2.0)); // Integer and not negative
assert!(!positive_integers.contains(&-3.0)); // Integer but negative
assert!(!positive_integers.contains(&1.5)); // Not an integer§Performance
- Time Complexity: O(1) for creation, O(f1 + f2) for evaluation where f1 and f2 are the complexities of the component predicates
- Memory Usage: O(1) - Creates a new predicate with references to existing ones
- Short-circuit Evaluation: Returns early if the first predicate evaluates to false
Sourcepub fn negate(&self) -> Predicate<A>where
A: 'static,
pub fn negate(&self) -> Predicate<A>where
A: 'static,
Returns a predicate that is the negation of this predicate.
The resulting predicate evaluates to true for inputs where this predicate
evaluates to false, and vice versa.
§Returns
A new Predicate<A> representing the logical negation
§Examples
use rustica::datatypes::wrapper::predicate::Predicate;
let is_even = Predicate::new(|x: &i32| *x % 2 == 0);
let is_odd = is_even.negate();
assert!(!is_odd.contains(&2));
assert!(is_odd.contains(&3));§Performance
- Time Complexity: O(1) for creation, O(f) for evaluation where f is the complexity of the original predicate
- Memory Usage: O(1) - Creates a new predicate with a reference to the existing one
Trait Implementations§
Source§impl<A: 'static> Monoid for Predicate<A>
impl<A: 'static> Monoid for Predicate<A>
Source§fn empty() -> Self
fn empty() -> Self
Returns the identity element for the combine operation: a predicate that always returns false.
This represents the empty set in set theory, which when unioned with any other set,
yields that other set unchanged. Similarly, when this empty predicate is combined with
any other predicate using combine (logical OR), the result is equivalent to the other predicate.
§Performance
- Time Complexity: O(1) for both creation and evaluation
- Memory Usage: Minimal, just stores an Rc to a trivial function
- Evaluation: Always returns false regardless of input
§Type Class Laws
§Left Identity: empty().combine(a) = a
use rustica::datatypes::wrapper::predicate::Predicate;
use rustica::traits::monoid::Monoid;
use rustica::traits::semigroup::Semigroup;
let is_even = Predicate::new(|x: &i32| *x % 2 == 0);
let test_values = [-10, -5, -2, -1, 0, 1, 2, 5, 10];
// Verify left identity law
fn verify_left_identity(a: &Predicate<i32>, x: i32) -> bool {
let empty = Predicate::<i32>::empty();
empty.combine(a).contains(&x) == a.contains(&x)
}
// Test with multiple values
for &val in test_values.iter() {
assert!(verify_left_identity(&is_even, val));
}§Right Identity: a.combine(empty()) = a
use rustica::datatypes::wrapper::predicate::Predicate;
use rustica::traits::monoid::Monoid;
use rustica::traits::semigroup::Semigroup;
let is_positive = Predicate::new(|x: &i32| *x > 0);
let test_values = [-10, -5, -2, -1, 0, 1, 2, 5, 10];
// Verify right identity law
fn verify_right_identity(a: &Predicate<i32>, x: i32) -> bool {
let empty = Predicate::<i32>::empty();
a.combine(&empty).contains(&x) == a.contains(&x)
}
// Test with multiple values
for &val in test_values.iter() {
assert!(verify_right_identity(&is_positive, val));
}§Examples
use rustica::datatypes::wrapper::predicate::Predicate;
use rustica::traits::monoid::Monoid;
use rustica::traits::semigroup::Semigroup;
// Create the empty predicate
let empty_pred = Predicate::<i32>::empty();
// It always returns false
assert!(!empty_pred.contains(&42));
assert!(!empty_pred.contains(&-7));
assert!(!empty_pred.contains(&0));
// Combining with other predicates
let is_positive = Predicate::new(|x: &i32| *x > 0);
let combined = empty_pred.combine(&is_positive);
// The result is equivalent to the non-empty predicate
assert!(combined.contains(&5));
assert!(!combined.contains(&-5));Source§impl<A: 'static> Semigroup for Predicate<A>
impl<A: 'static> Semigroup for Predicate<A>
Source§fn combine(&self, other: &Self) -> Self
fn combine(&self, other: &Self) -> Self
Combines two predicates using logical OR operation (union).
The resulting predicate will evaluate to true for an input if either
this predicate or the other predicate evaluates to true for that input.
This is equivalent to the union of the two sets defined by these predicates.
§Performance
- Time Complexity: O(1) for creation, O(f1 + f2) for evaluation where f1 and f2 are the complexities of the component predicates
- Memory Usage: O(1) - Creates a new predicate with references to existing predicates
- Short-circuit Evaluation: Returns early if the first predicate evaluates to true
- Cloning: Only the Rc pointers are cloned, not the underlying functions
§Type Class Laws
§Associativity: (a combine b) combine c = a combine (b combine c)
use rustica::datatypes::wrapper::predicate::Predicate;
use rustica::traits::semigroup::Semigroup;
// Define three simple predicates
let is_even = Predicate::new(|x: &i32| *x % 2 == 0);
let is_positive = Predicate::new(|x: &i32| *x > 0);
let is_multiple_of_3 = Predicate::new(|x: &i32| *x % 3 == 0);
// Test values
let test_values = [-6, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 9, 12];
// Verify associativity
fn verify_associativity(a: &Predicate<i32>, b: &Predicate<i32>, c: &Predicate<i32>, x: &i32) -> bool {
let left = a.combine(&b).combine(c).contains(x);
let right = a.combine(&b.combine(c)).contains(x);
left == right
}
// Verify the law for all test values
for &val in test_values.iter() {
assert!(verify_associativity(&is_even, &is_positive, &is_multiple_of_3, &val));
}§Examples
use rustica::datatypes::wrapper::predicate::Predicate;
use rustica::traits::semigroup::Semigroup;
let is_even = Predicate::new(|x: &i32| *x % 2 == 0);
let is_large = Predicate::new(|x: &i32| *x > 100);
// Combine predicates using Semigroup trait
let is_even_or_large = is_even.combine(&is_large);
assert!(is_even_or_large.contains(&2)); // Even but not large
assert!(is_even_or_large.contains(&200)); // Both even and large
assert!(is_even_or_large.contains(&101)); // Large but not even
assert!(!is_even_or_large.contains(&51)); // Neither even nor largeSource§fn combine_owned(self, other: Self) -> Self
fn combine_owned(self, other: Self) -> Self
Combines two predicates by consuming them, using logical OR operation (union).
This is the ownership-consuming variant of combine. The resulting predicate
will evaluate to true for an input if either of the original predicates
would evaluate to true for that input.
§Performance
- Time Complexity: O(1) for creation, O(f1 + f2) for evaluation
- Memory Usage: More efficient than
combinewhen both predicates are no longer needed separately - Ownership: Consumes both predicates rather than cloning references
§Examples
use rustica::datatypes::wrapper::predicate::Predicate;
use rustica::traits::semigroup::Semigroup;
let is_divisible_by_2 = Predicate::new(|x: &i32| *x % 2 == 0);
let is_divisible_by_3 = Predicate::new(|x: &i32| *x % 3 == 0);
// Consume both predicates to create a new one
let is_divisible_by_2_or_3 = is_divisible_by_2.combine_owned(is_divisible_by_3);
assert!(is_divisible_by_2_or_3.contains(&6)); // Divisible by both 2 and 3
assert!(is_divisible_by_2_or_3.contains(&4)); // Divisible by 2 only
assert!(is_divisible_by_2_or_3.contains(&9)); // Divisible by 3 only
assert!(!is_divisible_by_2_or_3.contains(&5)); // Divisible by neitherAuto Trait Implementations§
impl<A> !RefUnwindSafe for Predicate<A>
impl<A> !Send for Predicate<A>
impl<A> !Sync for Predicate<A>
impl<A> !UnwindSafe for Predicate<A>
impl<A> Freeze for Predicate<A>
impl<A> Unpin for Predicate<A>
impl<A> UnsafeUnpin for Predicate<A>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> PureExt for Twhere
T: Clone,
impl<T> PureExt for Twhere
T: Clone,
Source§fn to_pure_owned<P>(self) -> P::Output<Self>
fn to_pure_owned<P>(self) -> P::Output<Self>
Source§fn pair_with<P, U>(&self, other: &U) -> P::Output<(Self, U)>
fn pair_with<P, U>(&self, other: &U) -> P::Output<(Self, U)>
Source§impl<T> SemigroupExt for Twhere
T: Semigroup,
impl<T> SemigroupExt for Twhere
T: Semigroup,
Source§fn combine_all<I>(self, others: I) -> Selfwhere
I: IntoIterator<Item = Self>,
Self: Sized,
fn combine_all<I>(self, others: I) -> Selfwhere
I: IntoIterator<Item = Self>,
Self: Sized,
self with all the values in an iterator. Read more