Expand description
§Predicate Abstraction
Provides a Rust implementation similar to Java’s Predicate interface
for condition testing and logical composition.
§Core Semantics
A Predicate is fundamentally a pure judgment operation that tests whether a value satisfies a specific condition. It should be:
- Read-only: Does not modify the tested value
- Side-effect free: Does not change external state (from the user’s perspective)
- Repeatable: Same input should produce the same result
- Deterministic: Judgment logic should be predictable
§Design Philosophy
This module follows these principles:
- Single Trait: Only one
Predicate<T>trait with&self, keeping the API simple and semantically clear - No PredicateMut: All stateful scenarios use interior mutability
(
RefCell,Cell,Mutex) instead of&mut self - No PredicateOnce: Violates predicate semantics - judgments should be repeatable
- Three Implementations:
BoxPredicate,RcPredicate, andArcPredicatecover all ownership scenarios
§Type Selection Guide
| Scenario | Recommended Type | Reason |
|---|---|---|
| One-time use | BoxPredicate | Single ownership, no overhead |
| Multi-threaded | ArcPredicate | Thread-safe, clonable |
| Single-threaded reuse | RcPredicate | Better performance |
| Stateful predicate | Any type + RefCell/Cell/Mutex | Interior mutability |
§Examples
§Basic Usage with Closures
use prism3_function::predicate::Predicate;
let is_positive = |x: &i32| *x > 0;
assert!(is_positive.test(&5));
assert!(!is_positive.test(&-3));§BoxPredicate - Single Ownership
use prism3_function::predicate::{Predicate, BoxPredicate};
let pred = BoxPredicate::new(|x: &i32| *x > 0)
.and(BoxPredicate::new(|x| x % 2 == 0));
assert!(pred.test(&4));§Closure Composition with Extension Methods
Closures automatically gain and, or, not methods through the
FnPredicateOps extension trait, returning BoxPredicate:
use prism3_function::predicate::{Predicate, FnPredicateOps, BoxPredicate};
// Compose closures directly - result is BoxPredicate
let is_positive = |x: &i32| *x > 0;
let is_even = |x: &i32| x % 2 == 0;
let positive_and_even = is_positive.and(is_even);
assert!(positive_and_even.test(&4));
assert!(!positive_and_even.test(&3));
// Can chain multiple operations
let pred = (|x: &i32| *x > 0)
.and(|x: &i32| x % 2 == 0)
.and(BoxPredicate::new(|x: &i32| *x < 100));
assert!(pred.test(&42));
// Use `or` for disjunction
let negative_or_large = (|x: &i32| *x < 0)
.or(|x: &i32| *x > 100);
assert!(negative_or_large.test(&-5));
assert!(negative_or_large.test(&200));
// Use `not` for negation
let not_zero = (|x: &i32| *x == 0).not();
assert!(not_zero.test(&5));
assert!(!not_zero.test(&0));§Complex Predicate Composition
Build complex predicates by mixing closures and predicate types:
use prism3_function::predicate::{Predicate, BoxPredicate, FnPredicateOps};
// Start with a closure, compose with BoxPredicate
let in_range = (|x: &i32| *x >= 0)
.and(BoxPredicate::new(|x| *x <= 100));
// Use in filtering
let numbers = vec![-10, 5, 50, 150, 75];
let filtered: Vec<_> = numbers.iter()
.copied()
.filter(in_range.into_fn())
.collect();
assert_eq!(filtered, vec![5, 50, 75]);§RcPredicate - Single-threaded Reuse
use prism3_function::predicate::{Predicate, RcPredicate};
let pred = RcPredicate::new(|x: &i32| *x > 0);
let combined1 = pred.and(RcPredicate::new(|x| x % 2 == 0));
let combined2 = pred.or(RcPredicate::new(|x| *x > 100));
// Original predicate is still usable
assert!(pred.test(&5));§ArcPredicate - Thread-safe Sharing
use prism3_function::predicate::{Predicate, ArcPredicate};
use std::thread;
let pred = ArcPredicate::new(|x: &i32| *x > 0);
let pred_clone = pred.clone();
let handle = thread::spawn(move || {
pred_clone.test(&10)
});
assert!(handle.join().unwrap());
assert!(pred.test(&5)); // Original still usable§Stateful Predicates with Interior Mutability
use prism3_function::predicate::{Predicate, BoxPredicate};
use std::cell::Cell;
let count = Cell::new(0);
let pred = BoxPredicate::new(move |x: &i32| {
count.set(count.get() + 1);
*x > 0
});
// No need for `mut` - interior mutability handles state
assert!(pred.test(&5));
assert!(!pred.test(&-3));§Author
Haixing Hu
Structs§
- ArcPredicate
- An Arc-based predicate with thread-safe shared ownership.
- BoxPredicate
- A Box-based predicate with single ownership.
- RcPredicate
- An Rc-based predicate with single-threaded shared ownership.
Traits§
- FnPredicate
Ops - Extension trait providing logical composition methods for closures.
- Predicate
- A predicate trait for testing whether a value satisfies a condition.