prism3_function/predicates/
predicate.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025.
4 *    3-Prism Co. Ltd.
5 *
6 *    All rights reserved.
7 *
8 ******************************************************************************/
9//! # Predicate Abstraction
10//!
11//! Provides a Rust implementation similar to Java's `Predicate` interface
12//! for condition testing and logical composition.
13//!
14//! ## Core Semantics
15//!
16//! A **Predicate** is fundamentally a pure judgment operation that tests
17//! whether a value satisfies a specific condition. It should be:
18//!
19//! - **Read-only**: Does not modify the tested value
20//! - **Side-effect free**: Does not change external state (from the user's
21//!   perspective)
22//! - **Repeatable**: Same input should produce the same result
23//! - **Deterministic**: Judgment logic should be predictable
24//!
25//! It is similar to the `Fn(&T) -> bool` trait in the standard library.
26//!
27//! ## Design Philosophy
28//!
29//! This module follows these principles:
30//!
31//! 1. **Single Trait**: Only one `Predicate<T>` trait with `&self`, keeping
32//!    the API simple and semantically clear
33//! 2. **No PredicateMut**: All stateful scenarios use interior mutability
34//!    (`RefCell`, `Cell`, `Mutex`) instead of `&mut self`
35//! 3. **No PredicateOnce**: Violates predicate semantics - judgments should
36//!    be repeatable
37//! 4. **Three Implementations**: `BoxPredicate`, `RcPredicate`, and
38//!    `ArcPredicate` cover all ownership scenarios
39//!
40//! ## Type Selection Guide
41//!
42//! | Scenario | Recommended Type | Reason |
43//! |----------|------------------|--------|
44//! | One-time use | `BoxPredicate` | Single ownership, no overhead |
45//! | Multi-threaded | `ArcPredicate` | Thread-safe, clonable |
46//! | Single-threaded reuse | `RcPredicate` | Better performance |
47//! | Stateful predicate | Any type + `RefCell`/`Cell`/`Mutex` | Interior mutability |
48//!
49//! ## Examples
50//!
51//! ### Basic Usage with Closures
52//!
53//! ```rust
54//! use prism3_function::predicate::Predicate;
55//!
56//! let is_positive = |x: &i32| *x > 0;
57//! assert!(is_positive.test(&5));
58//! assert!(!is_positive.test(&-3));
59//! ```
60//!
61//! ### BoxPredicate - Single Ownership
62//!
63//! ```rust
64//! use prism3_function::predicate::{Predicate, BoxPredicate};
65//!
66//! let pred = BoxPredicate::new(|x: &i32| *x > 0)
67//!     .and(BoxPredicate::new(|x| x % 2 == 0));
68//! assert!(pred.test(&4));
69//! ```
70//!
71//! ### Closure Composition with Extension Methods
72//!
73//! Closures automatically gain `and`, `or`, `not` methods through the
74//! `FnPredicateOps` extension trait, returning `BoxPredicate`:
75//!
76//! ```rust
77//! use prism3_function::predicate::{Predicate, FnPredicateOps, BoxPredicate};
78//!
79//! // Compose closures directly - result is BoxPredicate
80//! let is_positive = |x: &i32| *x > 0;
81//! let is_even = |x: &i32| x % 2 == 0;
82//!
83//! let positive_and_even = is_positive.and(is_even);
84//! assert!(positive_and_even.test(&4));
85//! assert!(!positive_and_even.test(&3));
86//!
87//! // Can chain multiple operations
88//! let pred = (|x: &i32| *x > 0)
89//!     .and(|x: &i32| x % 2 == 0)
90//!     .and(BoxPredicate::new(|x: &i32| *x < 100));
91//! assert!(pred.test(&42));
92//!
93//! // Use `or` for disjunction
94//! let negative_or_large = (|x: &i32| *x < 0)
95//!     .or(|x: &i32| *x > 100);
96//! assert!(negative_or_large.test(&-5));
97//! assert!(negative_or_large.test(&200));
98//!
99//! // Use `not` for negation
100//! let not_zero = (|x: &i32| *x == 0).not();
101//! assert!(not_zero.test(&5));
102//! assert!(!not_zero.test(&0));
103//! ```
104//!
105//! ### Complex Predicate Composition
106//!
107//! Build complex predicates by mixing closures and predicate types:
108//!
109//! ```rust
110//! use prism3_function::predicate::{Predicate, BoxPredicate, FnPredicateOps};
111//!
112//! // Start with a closure, compose with BoxPredicate
113//! let in_range = (|x: &i32| *x >= 0)
114//!     .and(BoxPredicate::new(|x| *x <= 100));
115//!
116//! // Use in filtering
117//! let numbers = vec![-10, 5, 50, 150, 75];
118//! let filtered: Vec<_> = numbers.iter()
119//!     .copied()
120//!     .filter(in_range.into_fn())
121//!     .collect();
122//! assert_eq!(filtered, vec![5, 50, 75]);
123//! ```
124//!
125//! ### RcPredicate - Single-threaded Reuse
126//!
127//! ```rust
128//! use prism3_function::predicate::{Predicate, RcPredicate};
129//!
130//! let pred = RcPredicate::new(|x: &i32| *x > 0);
131//! let combined1 = pred.and(RcPredicate::new(|x| x % 2 == 0));
132//! let combined2 = pred.or(RcPredicate::new(|x| *x > 100));
133//!
134//! // Original predicate is still usable
135//! assert!(pred.test(&5));
136//! ```
137//!
138//! ### ArcPredicate - Thread-safe Sharing
139//!
140//! ```rust
141//! use prism3_function::predicate::{Predicate, ArcPredicate};
142//! use std::thread;
143//!
144//! let pred = ArcPredicate::new(|x: &i32| *x > 0);
145//! let pred_clone = pred.clone();
146//!
147//! let handle = thread::spawn(move || {
148//!     pred_clone.test(&10)
149//! });
150//!
151//! assert!(handle.join().unwrap());
152//! assert!(pred.test(&5));  // Original still usable
153//! ```
154//!
155//! ### Stateful Predicates with Interior Mutability
156//!
157//! ```rust
158//! use prism3_function::predicate::{Predicate, BoxPredicate};
159//! use std::cell::Cell;
160//!
161//! let count = Cell::new(0);
162//! let pred = BoxPredicate::new(move |x: &i32| {
163//!     count.set(count.get() + 1);
164//!     *x > 0
165//! });
166//!
167//! // No need for `mut` - interior mutability handles state
168//! assert!(pred.test(&5));
169//! assert!(!pred.test(&-3));
170//! ```
171//!
172//! ## Author
173//!
174//! Haixing Hu
175use std::rc::Rc;
176use std::sync::Arc;
177
178use crate::macros::{
179    impl_arc_conversions,
180    impl_box_conversions,
181    impl_closure_trait,
182    impl_rc_conversions,
183};
184use crate::predicates::macros::{
185    constants::{
186        ALWAYS_FALSE_NAME,
187        ALWAYS_TRUE_NAME,
188    },
189    impl_box_predicate_methods,
190    impl_predicate_clone,
191    impl_predicate_common_methods,
192    impl_predicate_debug_display,
193    impl_shared_predicate_methods,
194};
195
196/// A predicate trait for testing whether a value satisfies a condition.
197///
198/// This trait represents a **pure judgment operation** - it tests whether
199/// a given value meets certain criteria without modifying either the value
200/// or the predicate itself (from the user's perspective). This semantic
201/// clarity distinguishes predicates from consumers or transformers.
202///
203/// ## Design Rationale
204///
205/// This is a **minimal trait** that only defines:
206/// - The core `test` method using `&self` (immutable borrow)
207/// - Type conversion methods (`into_box`, `into_rc`, `into_arc`)
208/// - Closure conversion method (`into_fn`)
209///
210/// Logical composition methods (`and`, `or`, `not`) are intentionally
211/// **not** part of the trait. Instead, they are implemented on concrete
212/// types (`BoxPredicate`, `RcPredicate`, `ArcPredicate`), allowing each
213/// implementation to maintain its specific ownership characteristics:
214///
215/// - `BoxPredicate`: Methods consume `self` (single ownership)
216/// - `RcPredicate`: Methods borrow `&self` (shared ownership)
217/// - `ArcPredicate`: Methods borrow `&self` (thread-safe shared ownership)
218///
219/// ## Why `&self` Instead of `&mut self`?
220///
221/// Predicates use `&self` because:
222///
223/// 1. **Semantic Clarity**: A predicate is a judgment, not a mutation
224/// 2. **Flexibility**: Can be used in immutable contexts
225/// 3. **Simplicity**: No need for `mut` in user code
226/// 4. **Interior Mutability**: State (if needed) can be managed with
227///    `RefCell`, `Cell`, or `Mutex`
228///
229/// ## Automatic Implementation for Closures
230///
231/// Any closure matching `Fn(&T) -> bool` automatically implements this
232/// trait, providing seamless integration with Rust's closure system.
233///
234/// ## Examples
235///
236/// ### Basic Usage
237///
238/// ```rust
239/// use prism3_function::predicate::Predicate;
240///
241/// let is_positive = |x: &i32| *x > 0;
242/// assert!(is_positive.test(&5));
243/// assert!(!is_positive.test(&-3));
244/// ```
245///
246/// ### Type Conversion
247///
248/// ```rust
249/// use prism3_function::predicate::{Predicate, BoxPredicate};
250///
251/// let closure = |x: &i32| *x > 0;
252/// let boxed: BoxPredicate<i32> = closure.into_box();
253/// assert!(boxed.test(&5));
254/// ```
255///
256/// ### Stateful Predicate with Interior Mutability
257///
258/// ```rust
259/// use prism3_function::predicate::{Predicate, BoxPredicate};
260/// use std::cell::Cell;
261///
262/// let count = Cell::new(0);
263/// let counting_pred = BoxPredicate::new(move |x: &i32| {
264///     count.set(count.get() + 1);
265///     *x > 0
266/// });
267///
268/// // Note: No `mut` needed - interior mutability handles state
269/// assert!(counting_pred.test(&5));
270/// assert!(!counting_pred.test(&-3));
271/// ```
272///
273/// ## Author
274///
275/// Haixing Hu
276pub trait Predicate<T> {
277    /// Tests whether the given value satisfies this predicate.
278    ///
279    /// # Parameters
280    ///
281    /// * `value` - The value to test.
282    ///
283    /// # Returns
284    ///
285    /// `true` if the value satisfies this predicate, `false` otherwise.
286    fn test(&self, value: &T) -> bool;
287
288    /// Converts this predicate into a `BoxPredicate`.
289    ///
290    /// The default implementation wraps the predicate in a closure that
291    /// calls the `test` method. Concrete types may override this with
292    /// more efficient implementations.
293    ///
294    /// # Returns
295    ///
296    /// A `BoxPredicate` wrapping this predicate.
297    fn into_box(self) -> BoxPredicate<T>
298    where
299        Self: Sized + 'static,
300        T: 'static,
301    {
302        BoxPredicate::new(move |value: &T| self.test(value))
303    }
304
305    /// Converts this predicate into an `RcPredicate`.
306    ///
307    /// The default implementation wraps the predicate in a closure that
308    /// calls the `test` method. Concrete types may override this with
309    /// more efficient implementations.
310    ///
311    /// # Returns
312    ///
313    /// An `RcPredicate` wrapping this predicate.
314    fn into_rc(self) -> RcPredicate<T>
315    where
316        Self: Sized + 'static,
317        T: 'static,
318    {
319        RcPredicate::new(move |value: &T| self.test(value))
320    }
321
322    /// Converts this predicate into an `ArcPredicate`.
323    ///
324    /// The default implementation wraps the predicate in a closure that
325    /// calls the `test` method. Concrete types may override this with
326    /// more efficient implementations.
327    ///
328    /// # Returns
329    ///
330    /// An `ArcPredicate` wrapping this predicate.
331    fn into_arc(self) -> ArcPredicate<T>
332    where
333        Self: Sized + Send + Sync + 'static,
334        T: 'static,
335    {
336        ArcPredicate::new(move |value: &T| self.test(value))
337    }
338
339    /// Converts this predicate into a closure that can be used directly
340    /// with standard library methods.
341    ///
342    /// This method consumes the predicate and returns a closure with
343    /// signature `Fn(&T) -> bool`. Since `Fn` is a subtrait of `FnMut`,
344    /// the returned closure can be used in any context that requires
345    /// either `Fn(&T) -> bool` or `FnMut(&T) -> bool`, making it
346    /// compatible with methods like `Iterator::filter`,
347    /// `Iterator::filter_map`, `Vec::retain`, and similar standard
348    /// library APIs.
349    ///
350    /// The default implementation returns a closure that calls the
351    /// `test` method. Concrete types may override this with more
352    /// efficient implementations.
353    ///
354    /// # Returns
355    ///
356    /// A closure implementing `Fn(&T) -> bool` (also usable as
357    /// `FnMut(&T) -> bool`).
358    ///
359    /// # Examples
360    ///
361    /// ## Using with `Iterator::filter` (requires `FnMut`)
362    ///
363    /// ```rust
364    /// use prism3_function::predicate::{Predicate, BoxPredicate};
365    ///
366    /// let pred = BoxPredicate::new(|x: &i32| *x > 0);
367    ///
368    /// let numbers = vec![-2, -1, 0, 1, 2, 3];
369    /// let positives: Vec<_> = numbers.iter()
370    ///     .copied()
371    ///     .filter(pred.into_fn())
372    ///     .collect();
373    /// assert_eq!(positives, vec![1, 2, 3]);
374    /// ```
375    ///
376    /// ## Using with `Vec::retain` (requires `FnMut`)
377    ///
378    /// ```rust
379    /// use prism3_function::predicate::{Predicate, BoxPredicate};
380    ///
381    /// let pred = BoxPredicate::new(|x: &i32| *x % 2 == 0);
382    /// let mut numbers = vec![1, 2, 3, 4, 5, 6];
383    /// numbers.retain(pred.into_fn());
384    /// assert_eq!(numbers, vec![2, 4, 6]);
385    /// ```
386    fn into_fn(self) -> impl Fn(&T) -> bool
387    where
388        Self: Sized + 'static,
389        T: 'static,
390    {
391        move |value: &T| self.test(value)
392    }
393
394    /// Converts a reference to this predicate into a `BoxPredicate`.
395    ///
396    /// This method clones the predicate and then converts it to a
397    /// `BoxPredicate`. The original predicate remains usable after this call.
398    ///
399    /// # Returns
400    ///
401    /// A `BoxPredicate` wrapping a clone of this predicate.
402    fn to_box(&self) -> BoxPredicate<T>
403    where
404        Self: Clone + Sized + 'static,
405        T: 'static,
406    {
407        self.clone().into_box()
408    }
409
410    /// Converts a reference to this predicate into an `RcPredicate`.
411    ///
412    /// This method clones the predicate and then converts it to an
413    /// `RcPredicate`. The original predicate remains usable after this call.
414    ///
415    /// # Returns
416    ///
417    /// An `RcPredicate` wrapping a clone of this predicate.
418    fn to_rc(&self) -> RcPredicate<T>
419    where
420        Self: Clone + Sized + 'static,
421        T: 'static,
422    {
423        self.clone().into_rc()
424    }
425
426    /// Converts a reference to this predicate into an `ArcPredicate`.
427    ///
428    /// This method clones the predicate and then converts it to an
429    /// `ArcPredicate`. The original predicate remains usable after this call.
430    ///
431    /// # Returns
432    ///
433    /// An `ArcPredicate` wrapping a clone of this predicate.
434    fn to_arc(&self) -> ArcPredicate<T>
435    where
436        Self: Clone + Sized + Send + Sync + 'static,
437        T: 'static,
438    {
439        self.clone().into_arc()
440    }
441
442    /// Converts a reference to this predicate into a closure that can be
443    /// used directly with standard library methods.
444    ///
445    /// This method clones the predicate and then converts it to a closure.
446    /// The original predicate remains usable after this call.
447    ///
448    /// The returned closure has signature `Fn(&T) -> bool`. Since `Fn` is a
449    /// subtrait of `FnMut`, it can be used in any context that requires
450    /// either `Fn(&T) -> bool` or `FnMut(&T) -> bool`, making it compatible
451    /// with methods like `Iterator::filter`, `Iterator::filter_map`,
452    /// `Vec::retain`, and similar standard library APIs.
453    ///
454    /// # Returns
455    ///
456    /// A closure implementing `Fn(&T) -> bool` (also usable as
457    /// `FnMut(&T) -> bool`).
458    fn to_fn(&self) -> impl Fn(&T) -> bool
459    where
460        Self: Clone + Sized + 'static,
461        T: 'static,
462    {
463        self.clone().into_fn()
464    }
465}
466
467/// A Box-based predicate with single ownership.
468///
469/// This type is suitable for one-time use scenarios where the predicate does
470/// not need to be cloned or shared. Composition methods consume `self`,
471/// reflecting the single-ownership model.
472///
473/// # Examples
474///
475/// ```rust
476/// use prism3_function::predicate::{Predicate, BoxPredicate};
477///
478/// let pred = BoxPredicate::new(|x: &i32| *x > 0);
479/// assert!(pred.test(&5));
480///
481/// // Chaining consumes the predicate
482/// let combined = pred.and(BoxPredicate::new(|x| x % 2 == 0));
483/// assert!(combined.test(&4));
484/// ```
485///
486/// # Author
487///
488/// Haixing Hu
489pub struct BoxPredicate<T> {
490    function: Box<dyn Fn(&T) -> bool>,
491    name: Option<String>,
492}
493
494impl<T: 'static> BoxPredicate<T> {
495    // Generates: new(), new_with_name(), name(), set_name(), always_true(), always_false()
496    impl_predicate_common_methods!(BoxPredicate<T>, (Fn(&T) -> bool + 'static), |f| Box::new(f));
497
498    // Generates: and(), or(), not(), nand(), xor(), nor()
499    impl_box_predicate_methods!(BoxPredicate<T>);
500}
501
502// Generates: impl Debug for BoxPredicate<T> and impl Display for BoxPredicate<T>
503impl_predicate_debug_display!(BoxPredicate<T>);
504
505// Implements Predicate trait for BoxPredicate<T>
506impl<T: 'static> Predicate<T> for BoxPredicate<T> {
507    fn test(&self, value: &T) -> bool {
508        (self.function)(value)
509    }
510
511    // Generates: into_box(), into_rc(), into_fn()
512    impl_box_conversions!(
513        BoxPredicate<T>,
514        RcPredicate,
515        Fn(&T) -> bool
516    );
517}
518
519/// An Rc-based predicate with single-threaded shared ownership.
520///
521/// This type is suitable for scenarios where the predicate needs to be
522/// reused in a single-threaded context. Composition methods borrow `&self`,
523/// allowing the original predicate to remain usable after composition.
524///
525/// # Examples
526///
527/// ```rust
528/// use prism3_function::predicate::{Predicate, RcPredicate};
529///
530/// let pred = RcPredicate::new(|x: &i32| *x > 0);
531/// assert!(pred.test(&5));
532///
533/// // Original predicate remains usable after composition
534/// let combined = pred.and(RcPredicate::new(|x| x % 2 == 0));
535/// assert!(pred.test(&5));  // Still works
536/// ```
537///
538/// # Author
539///
540/// Haixing Hu
541pub struct RcPredicate<T> {
542    function: Rc<dyn Fn(&T) -> bool>,
543    name: Option<String>,
544}
545
546impl<T: 'static> RcPredicate<T> {
547    // Generates: new(), new_with_name(), name(), set_name(), always_true(), always_false()
548    impl_predicate_common_methods!(RcPredicate<T>, (Fn(&T) -> bool + 'static), |f| Rc::new(f));
549
550    // Generates: and(), or(), not(), nand(), xor(), nor()
551    impl_shared_predicate_methods!(RcPredicate<T>, 'static);
552}
553
554// Generates: impl Clone for RcPredicate<T>
555impl_predicate_clone!(RcPredicate<T>);
556
557// Generates: impl Debug for RcPredicate<T> and impl Display for RcPredicate<T>
558impl_predicate_debug_display!(RcPredicate<T>);
559
560// Implements Predicate trait for RcPredicate<T>
561impl<T: 'static> Predicate<T> for RcPredicate<T> {
562    fn test(&self, value: &T) -> bool {
563        (self.function)(value)
564    }
565
566    // Generates: into_box(), into_rc(), into_fn(), to_box(), to_rc(), to_fn()
567    impl_rc_conversions!(
568        RcPredicate<T>,
569        BoxPredicate,
570        Fn(t: &T) -> bool
571    );
572}
573
574/// An Arc-based predicate with thread-safe shared ownership.
575///
576/// This type is suitable for scenarios where the predicate needs to be
577/// shared across threads. Composition methods borrow `&self`, allowing the
578/// original predicate to remain usable after composition.
579///
580/// # Examples
581///
582/// ```rust
583/// use prism3_function::predicate::{Predicate, ArcPredicate};
584///
585/// let pred = ArcPredicate::new(|x: &i32| *x > 0);
586/// assert!(pred.test(&5));
587///
588/// // Original predicate remains usable after composition
589/// let combined = pred.and(ArcPredicate::new(|x| x % 2 == 0));
590/// assert!(pred.test(&5));  // Still works
591///
592/// // Can be cloned and sent across threads
593/// let pred_clone = pred.clone();
594/// std::thread::spawn(move || {
595///     assert!(pred_clone.test(&10));
596/// }).join().unwrap();
597/// ```
598///
599/// # Author
600///
601/// Haixing Hu
602pub struct ArcPredicate<T> {
603    function: Arc<dyn Fn(&T) -> bool + Send + Sync>,
604    name: Option<String>,
605}
606
607impl<T: 'static> ArcPredicate<T> {
608    // Generates: new(), new_with_name(), name(), set_name(), always_true(), always_false()
609    impl_predicate_common_methods!(
610        ArcPredicate<T>,
611        (Fn(&T) -> bool + Send + Sync + 'static),
612        |f| Arc::new(f)
613    );
614
615    // Generates: and(), or(), not(), nand(), xor(), nor()
616    impl_shared_predicate_methods!(ArcPredicate<T>, Send + Sync + 'static);
617}
618
619// Generates: impl Clone for ArcPredicate<T>
620impl_predicate_clone!(ArcPredicate<T>);
621
622// Generates: impl Debug for ArcPredicate<T> and impl Display for ArcPredicate<T>
623impl_predicate_debug_display!(ArcPredicate<T>);
624
625// Implements Predicate trait for ArcPredicate<T>
626impl<T: 'static> Predicate<T> for ArcPredicate<T> {
627    fn test(&self, value: &T) -> bool {
628        (self.function)(value)
629    }
630
631    // Generates: into_box, into_rc, into_arc, into_fn, to_box, to_rc, to_arc, to_fn
632    impl_arc_conversions!(
633        ArcPredicate<T>,
634        BoxPredicate,
635        RcPredicate,
636        Fn(t: &T) -> bool
637    );
638}
639
640// Blanket implementation for all closures that match Fn(&T) -> bool
641impl_closure_trait!(
642    Predicate<T>,
643    test,
644    Fn(value: &T) -> bool
645);
646
647/// Extension trait providing logical composition methods for closures.
648///
649/// This trait is automatically implemented for all closures and function
650/// pointers that match `Fn(&T) -> bool`, enabling method chaining starting
651/// from a closure.
652///
653/// # Examples
654///
655/// ```rust
656/// use prism3_function::predicate::{Predicate, FnPredicateOps};
657///
658/// let is_positive = |x: &i32| *x > 0;
659/// let is_even = |x: &i32| x % 2 == 0;
660///
661/// // Combine predicates using extension methods
662/// let pred = is_positive.and(is_even);
663/// assert!(pred.test(&4));
664/// assert!(!pred.test(&3));
665/// ```
666///
667/// # Author
668///
669/// Haixing Hu
670pub trait FnPredicateOps<T>: Fn(&T) -> bool + Sized + 'static {
671    /// Returns a predicate that represents the logical AND of this predicate
672    /// and another.
673    ///
674    /// # Parameters
675    ///
676    /// * `other` - The other predicate to combine with. **Note: This parameter
677    ///   is passed by value and will transfer ownership.** If you need to
678    ///   preserve the original predicate, clone it first (if it implements
679    ///   `Clone`). Can be:
680    ///   - Another closure
681    ///   - A function pointer
682    ///   - A `BoxPredicate<T>`, `RcPredicate<T>`, or `ArcPredicate<T>`
683    ///
684    /// # Returns
685    ///
686    /// A `BoxPredicate` representing the logical AND.
687    ///
688    /// # Examples
689    ///
690    /// ```rust
691    /// use prism3_function::predicate::{Predicate, FnPredicateOps};
692    ///
693    /// let is_positive = |x: &i32| *x > 0;
694    /// let is_even = |x: &i32| x % 2 == 0;
695    ///
696    /// let combined = is_positive.and(is_even);
697    /// assert!(combined.test(&4));
698    /// assert!(!combined.test(&3));
699    /// ```
700    fn and<P>(self, other: P) -> BoxPredicate<T>
701    where
702        P: Predicate<T> + 'static,
703        T: 'static,
704    {
705        BoxPredicate::new(move |value: &T| self.test(value) && other.test(value))
706    }
707
708    /// Returns a predicate that represents the logical OR of this predicate
709    /// and another.
710    ///
711    /// # Parameters
712    ///
713    /// * `other` - The other predicate to combine with. **Note: This parameter
714    ///   is passed by value and will transfer ownership.** If you need to
715    ///   preserve the original predicate, clone it first (if it implements
716    ///   `Clone`). Can be:
717    ///   - Another closure
718    ///   - A function pointer
719    ///   - A `BoxPredicate<T>`, `RcPredicate<T>`, or `ArcPredicate<T>`
720    ///   - Any type implementing `Predicate<T>`
721    ///
722    /// # Returns
723    ///
724    /// A `BoxPredicate` representing the logical OR.
725    ///
726    /// # Examples
727    ///
728    /// ```rust
729    /// use prism3_function::predicate::{Predicate, FnPredicateOps};
730    ///
731    /// let is_negative = |x: &i32| *x < 0;
732    /// let is_large = |x: &i32| *x > 100;
733    ///
734    /// let combined = is_negative.or(is_large);
735    /// assert!(combined.test(&-5));
736    /// assert!(combined.test(&150));
737    /// assert!(!combined.test(&50));
738    /// ```
739    fn or<P>(self, other: P) -> BoxPredicate<T>
740    where
741        P: Predicate<T> + 'static,
742        T: 'static,
743    {
744        BoxPredicate::new(move |value: &T| self.test(value) || other.test(value))
745    }
746
747    /// Returns a predicate that represents the logical negation of this
748    /// predicate.
749    ///
750    /// # Returns
751    ///
752    /// A `BoxPredicate` representing the logical negation.
753    fn not(self) -> BoxPredicate<T>
754    where
755        T: 'static,
756    {
757        BoxPredicate::new(move |value: &T| !self.test(value))
758    }
759
760    /// Returns a predicate that represents the logical NAND (NOT AND) of this
761    /// predicate and another.
762    ///
763    /// NAND returns `true` unless both predicates are `true`.
764    /// Equivalent to `!(self AND other)`.
765    ///
766    /// # Parameters
767    ///
768    /// * `other` - The other predicate to combine with. **Note: This parameter
769    ///   is passed by value and will transfer ownership.** If you need to
770    ///   preserve the original predicate, clone it first (if it implements
771    ///   `Clone`). Accepts closures, function pointers, or any
772    ///   `Predicate<T>` implementation.
773    ///
774    /// # Returns
775    ///
776    /// A `BoxPredicate` representing the logical NAND.
777    ///
778    /// # Examples
779    ///
780    /// ```rust
781    /// use prism3_function::predicate::{Predicate, FnPredicateOps};
782    ///
783    /// let is_positive = |x: &i32| *x > 0;
784    /// let is_even = |x: &i32| x % 2 == 0;
785    ///
786    /// let nand = is_positive.nand(is_even);
787    /// assert!(nand.test(&3));   // !(true && false) = true
788    /// assert!(!nand.test(&4));  // !(true && true) = false
789    /// ```
790    fn nand<P>(self, other: P) -> BoxPredicate<T>
791    where
792        P: Predicate<T> + 'static,
793        T: 'static,
794    {
795        BoxPredicate::new(move |value: &T| !(self.test(value) && other.test(value)))
796    }
797
798    /// Returns a predicate that represents the logical XOR (exclusive OR) of
799    /// this predicate and another.
800    ///
801    /// XOR returns `true` if exactly one of the predicates is `true`.
802    ///
803    /// # Parameters
804    ///
805    /// * `other` - The other predicate to combine with. **Note: This parameter
806    ///   is passed by value and will transfer ownership.** If you need to
807    ///   preserve the original predicate, clone it first (if it implements
808    ///   `Clone`). Accepts closures, function pointers, or any
809    ///   `Predicate<T>` implementation.
810    ///
811    /// # Returns
812    ///
813    /// A `BoxPredicate` representing the logical XOR.
814    ///
815    /// # Examples
816    ///
817    /// ```rust
818    /// use prism3_function::predicate::{Predicate, FnPredicateOps};
819    ///
820    /// let is_positive = |x: &i32| *x > 0;
821    /// let is_even = |x: &i32| x % 2 == 0;
822    ///
823    /// let xor = is_positive.xor(is_even);
824    /// assert!(xor.test(&3));    // true ^ false = true
825    /// assert!(!xor.test(&4));   // true ^ true = false
826    /// assert!(!xor.test(&-1));  // false ^ false = false
827    /// ```
828    fn xor<P>(self, other: P) -> BoxPredicate<T>
829    where
830        P: Predicate<T> + 'static,
831        T: 'static,
832    {
833        BoxPredicate::new(move |value: &T| self.test(value) ^ other.test(value))
834    }
835
836    /// Returns a predicate that represents the logical NOR (NOT OR) of this
837    /// predicate and another.
838    ///
839    /// NOR returns `true` only when both predicates are `false`. Equivalent
840    /// to `!(self OR other)`.
841    ///
842    /// # Parameters
843    ///
844    /// * `other` - The other predicate to combine with. **Note: This parameter
845    ///   is passed by value and will transfer ownership.** If you need to
846    ///   preserve the original predicate, clone it first (if it implements
847    ///   `Clone`). Accepts closures, function pointers, or any
848    ///   `Predicate<T>` implementation.
849    ///
850    /// # Returns
851    ///
852    /// A `BoxPredicate` representing the logical NOR.
853    ///
854    /// # Examples
855    ///
856    /// ```rust
857    /// use prism3_function::predicate::{Predicate, FnPredicateOps};
858    ///
859    /// let is_positive = |x: &i32| *x > 0;
860    /// let is_even = |x: &i32| x % 2 == 0;
861    ///
862    /// let nor = is_positive.nor(is_even);
863    /// assert!(nor.test(&-3));   // !(false || false) = true
864    /// assert!(!nor.test(&4));   // !(true || true) = false
865    /// assert!(!nor.test(&3));   // !(true || false) = false
866    /// ```
867    fn nor<P>(self, other: P) -> BoxPredicate<T>
868    where
869        P: Predicate<T> + 'static,
870        T: 'static,
871    {
872        BoxPredicate::new(move |value: &T| !(self.test(value) || other.test(value)))
873    }
874}
875
876// Blanket implementation for all closures
877impl<T, F> FnPredicateOps<T> for F where F: Fn(&T) -> bool + 'static {}