Module predicate

Module predicate 

Source
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:

  1. Single Trait: Only one Predicate<T> trait with &self, keeping the API simple and semantically clear
  2. No PredicateMut: All stateful scenarios use interior mutability (RefCell, Cell, Mutex) instead of &mut self
  3. No PredicateOnce: Violates predicate semantics - judgments should be repeatable
  4. Three Implementations: BoxPredicate, RcPredicate, and ArcPredicate cover all ownership scenarios

§Type Selection Guide

ScenarioRecommended TypeReason
One-time useBoxPredicateSingle ownership, no overhead
Multi-threadedArcPredicateThread-safe, clonable
Single-threaded reuseRcPredicateBetter performance
Stateful predicateAny type + RefCell/Cell/MutexInterior 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§

FnPredicateOps
Extension trait providing logical composition methods for closures.
Predicate
A predicate trait for testing whether a value satisfies a condition.