qubit_function/predicates/predicate.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2025 - 2026.
4 * Haixing Hu, Qubit 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 qubit_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 qubit_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 qubit_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 qubit_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 qubit_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 qubit_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 qubit_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 qubit_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 qubit_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 qubit_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 qubit_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 qubit_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 {
390 move |value: &T| self.test(value)
391 }
392
393 /// Converts a reference to this predicate into a `BoxPredicate`.
394 ///
395 /// This method clones the predicate and then converts it to a
396 /// `BoxPredicate`. The original predicate remains usable after this call.
397 ///
398 /// # Returns
399 ///
400 /// A `BoxPredicate` wrapping a clone of this predicate.
401 fn to_box(&self) -> BoxPredicate<T>
402 where
403 Self: Clone + Sized + 'static,
404 T: 'static,
405 {
406 self.clone().into_box()
407 }
408
409 /// Converts a reference to this predicate into an `RcPredicate`.
410 ///
411 /// This method clones the predicate and then converts it to an
412 /// `RcPredicate`. The original predicate remains usable after this call.
413 ///
414 /// # Returns
415 ///
416 /// An `RcPredicate` wrapping a clone of this predicate.
417 fn to_rc(&self) -> RcPredicate<T>
418 where
419 Self: Clone + Sized + 'static,
420 T: 'static,
421 {
422 self.clone().into_rc()
423 }
424
425 /// Converts a reference to this predicate into an `ArcPredicate`.
426 ///
427 /// This method clones the predicate and then converts it to an
428 /// `ArcPredicate`. The original predicate remains usable after this call.
429 ///
430 /// # Returns
431 ///
432 /// An `ArcPredicate` wrapping a clone of this predicate.
433 fn to_arc(&self) -> ArcPredicate<T>
434 where
435 Self: Clone + Sized + Send + Sync + 'static,
436 T: 'static,
437 {
438 self.clone().into_arc()
439 }
440
441 /// Converts a reference to this predicate into a closure that can be
442 /// used directly with standard library methods.
443 ///
444 /// This method clones the predicate and then converts it to a closure.
445 /// The original predicate remains usable after this call.
446 ///
447 /// The returned closure has signature `Fn(&T) -> bool`. Since `Fn` is a
448 /// subtrait of `FnMut`, it can be used in any context that requires
449 /// either `Fn(&T) -> bool` or `FnMut(&T) -> bool`, making it compatible
450 /// with methods like `Iterator::filter`, `Iterator::filter_map`,
451 /// `Vec::retain`, and similar standard library APIs.
452 ///
453 /// # Returns
454 ///
455 /// A closure implementing `Fn(&T) -> bool` (also usable as
456 /// `FnMut(&T) -> bool`).
457 fn to_fn(&self) -> impl Fn(&T) -> bool
458 where
459 Self: Clone + Sized + 'static,
460 {
461 self.clone().into_fn()
462 }
463}
464
465/// A Box-based predicate with single ownership.
466///
467/// This type is suitable for one-time use scenarios where the predicate does
468/// not need to be cloned or shared. Composition methods consume `self`,
469/// reflecting the single-ownership model.
470///
471/// # Examples
472///
473/// ```rust
474/// use qubit_function::predicate::{Predicate, BoxPredicate};
475///
476/// let pred = BoxPredicate::new(|x: &i32| *x > 0);
477/// assert!(pred.test(&5));
478///
479/// // Chaining consumes the predicate
480/// let combined = pred.and(BoxPredicate::new(|x| x % 2 == 0));
481/// assert!(combined.test(&4));
482/// ```
483///
484/// # Author
485///
486/// Haixing Hu
487pub struct BoxPredicate<T> {
488 function: Box<dyn Fn(&T) -> bool>,
489 name: Option<String>,
490}
491
492impl<T> BoxPredicate<T> {
493 // Generates: new(), new_with_name(), name(), set_name(), always_true(), always_false()
494 impl_predicate_common_methods!(BoxPredicate<T>, (Fn(&T) -> bool + 'static), |f| Box::new(f));
495
496 // Generates: and(), or(), not(), nand(), xor(), nor()
497 impl_box_predicate_methods!(BoxPredicate<T>);
498}
499
500// Generates: impl Debug for BoxPredicate<T> and impl Display for BoxPredicate<T>
501impl_predicate_debug_display!(BoxPredicate<T>);
502
503// Implements Predicate trait for BoxPredicate<T>
504impl<T> Predicate<T> for BoxPredicate<T> {
505 fn test(&self, value: &T) -> bool {
506 (self.function)(value)
507 }
508
509 // Generates: into_box(), into_rc(), into_fn()
510 impl_box_conversions!(
511 BoxPredicate<T>,
512 RcPredicate,
513 Fn(&T) -> bool
514 );
515}
516
517/// An Rc-based predicate with single-threaded shared ownership.
518///
519/// This type is suitable for scenarios where the predicate needs to be
520/// reused in a single-threaded context. Composition methods borrow `&self`,
521/// allowing the original predicate to remain usable after composition.
522///
523/// # Examples
524///
525/// ```rust
526/// use qubit_function::predicate::{Predicate, RcPredicate};
527///
528/// let pred = RcPredicate::new(|x: &i32| *x > 0);
529/// assert!(pred.test(&5));
530///
531/// // Original predicate remains usable after composition
532/// let combined = pred.and(RcPredicate::new(|x| x % 2 == 0));
533/// assert!(pred.test(&5)); // Still works
534/// ```
535///
536/// # Author
537///
538/// Haixing Hu
539pub struct RcPredicate<T> {
540 function: Rc<dyn Fn(&T) -> bool>,
541 name: Option<String>,
542}
543
544impl<T> RcPredicate<T> {
545 // Generates: new(), new_with_name(), name(), set_name(), always_true(), always_false()
546 impl_predicate_common_methods!(RcPredicate<T>, (Fn(&T) -> bool + 'static), |f| Rc::new(f));
547
548 // Generates: and(), or(), not(), nand(), xor(), nor()
549 impl_shared_predicate_methods!(RcPredicate<T>, 'static);
550}
551
552// Generates: impl Clone for RcPredicate<T>
553impl_predicate_clone!(RcPredicate<T>);
554
555// Generates: impl Debug for RcPredicate<T> and impl Display for RcPredicate<T>
556impl_predicate_debug_display!(RcPredicate<T>);
557
558// Implements Predicate trait for RcPredicate<T>
559impl<T> Predicate<T> for RcPredicate<T> {
560 fn test(&self, value: &T) -> bool {
561 (self.function)(value)
562 }
563
564 // Generates: into_box(), into_rc(), into_fn(), to_box(), to_rc(), to_fn()
565 impl_rc_conversions!(
566 RcPredicate<T>,
567 BoxPredicate,
568 Fn(t: &T) -> bool
569 );
570}
571
572/// An Arc-based predicate with thread-safe shared ownership.
573///
574/// This type is suitable for scenarios where the predicate needs to be
575/// shared across threads. Composition methods borrow `&self`, allowing the
576/// original predicate to remain usable after composition.
577///
578/// # Examples
579///
580/// ```rust
581/// use qubit_function::predicate::{Predicate, ArcPredicate};
582///
583/// let pred = ArcPredicate::new(|x: &i32| *x > 0);
584/// assert!(pred.test(&5));
585///
586/// // Original predicate remains usable after composition
587/// let combined = pred.and(ArcPredicate::new(|x| x % 2 == 0));
588/// assert!(pred.test(&5)); // Still works
589///
590/// // Can be cloned and sent across threads
591/// let pred_clone = pred.clone();
592/// std::thread::spawn(move || {
593/// assert!(pred_clone.test(&10));
594/// }).join().unwrap();
595/// ```
596///
597/// # Author
598///
599/// Haixing Hu
600pub struct ArcPredicate<T> {
601 function: Arc<dyn Fn(&T) -> bool + Send + Sync>,
602 name: Option<String>,
603}
604
605impl<T> ArcPredicate<T> {
606 // Generates: new(), new_with_name(), name(), set_name(), always_true(), always_false()
607 impl_predicate_common_methods!(
608 ArcPredicate<T>,
609 (Fn(&T) -> bool + Send + Sync + 'static),
610 |f| Arc::new(f)
611 );
612
613 // Generates: and(), or(), not(), nand(), xor(), nor()
614 impl_shared_predicate_methods!(ArcPredicate<T>, Send + Sync + 'static);
615}
616
617// Generates: impl Clone for ArcPredicate<T>
618impl_predicate_clone!(ArcPredicate<T>);
619
620// Generates: impl Debug for ArcPredicate<T> and impl Display for ArcPredicate<T>
621impl_predicate_debug_display!(ArcPredicate<T>);
622
623// Implements Predicate trait for ArcPredicate<T>
624impl<T> Predicate<T> for ArcPredicate<T> {
625 fn test(&self, value: &T) -> bool {
626 (self.function)(value)
627 }
628
629 // Generates: into_box, into_rc, into_arc, into_fn, to_box, to_rc, to_arc, to_fn
630 impl_arc_conversions!(
631 ArcPredicate<T>,
632 BoxPredicate,
633 RcPredicate,
634 Fn(t: &T) -> bool
635 );
636}
637
638// Blanket implementation for all closures that match Fn(&T) -> bool
639impl_closure_trait!(
640 Predicate<T>,
641 test,
642 Fn(value: &T) -> bool
643);
644
645/// Extension trait providing logical composition methods for closures.
646///
647/// This trait is automatically implemented for all closures and function
648/// pointers that match `Fn(&T) -> bool`, enabling method chaining starting
649/// from a closure.
650///
651/// # Examples
652///
653/// ```rust
654/// use qubit_function::predicate::{Predicate, FnPredicateOps};
655///
656/// let is_positive = |x: &i32| *x > 0;
657/// let is_even = |x: &i32| x % 2 == 0;
658///
659/// // Combine predicates using extension methods
660/// let pred = is_positive.and(is_even);
661/// assert!(pred.test(&4));
662/// assert!(!pred.test(&3));
663/// ```
664///
665/// # Author
666///
667/// Haixing Hu
668pub trait FnPredicateOps<T>: Fn(&T) -> bool + Sized {
669 /// Returns a predicate that represents the logical AND of this predicate
670 /// and another.
671 ///
672 /// # Parameters
673 ///
674 /// * `other` - The other predicate to combine with. **Note: This parameter
675 /// is passed by value and will transfer ownership.** If you need to
676 /// preserve the original predicate, clone it first (if it implements
677 /// `Clone`). Can be:
678 /// - Another closure
679 /// - A function pointer
680 /// - A `BoxPredicate<T>`, `RcPredicate<T>`, or `ArcPredicate<T>`
681 ///
682 /// # Returns
683 ///
684 /// A `BoxPredicate` representing the logical AND.
685 ///
686 /// # Examples
687 ///
688 /// ```rust
689 /// use qubit_function::predicate::{Predicate, FnPredicateOps};
690 ///
691 /// let is_positive = |x: &i32| *x > 0;
692 /// let is_even = |x: &i32| x % 2 == 0;
693 ///
694 /// let combined = is_positive.and(is_even);
695 /// assert!(combined.test(&4));
696 /// assert!(!combined.test(&3));
697 /// ```
698 fn and<P>(self, other: P) -> BoxPredicate<T>
699 where
700 Self: 'static,
701 P: Predicate<T> + 'static,
702 T: 'static,
703 {
704 BoxPredicate::new(move |value: &T| self.test(value) && other.test(value))
705 }
706
707 /// Returns a predicate that represents the logical OR of this predicate
708 /// and another.
709 ///
710 /// # Parameters
711 ///
712 /// * `other` - The other predicate to combine with. **Note: This parameter
713 /// is passed by value and will transfer ownership.** If you need to
714 /// preserve the original predicate, clone it first (if it implements
715 /// `Clone`). Can be:
716 /// - Another closure
717 /// - A function pointer
718 /// - A `BoxPredicate<T>`, `RcPredicate<T>`, or `ArcPredicate<T>`
719 /// - Any type implementing `Predicate<T>`
720 ///
721 /// # Returns
722 ///
723 /// A `BoxPredicate` representing the logical OR.
724 ///
725 /// # Examples
726 ///
727 /// ```rust
728 /// use qubit_function::predicate::{Predicate, FnPredicateOps};
729 ///
730 /// let is_negative = |x: &i32| *x < 0;
731 /// let is_large = |x: &i32| *x > 100;
732 ///
733 /// let combined = is_negative.or(is_large);
734 /// assert!(combined.test(&-5));
735 /// assert!(combined.test(&150));
736 /// assert!(!combined.test(&50));
737 /// ```
738 fn or<P>(self, other: P) -> BoxPredicate<T>
739 where
740 Self: 'static,
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 Self: 'static,
756 T: 'static,
757 {
758 BoxPredicate::new(move |value: &T| !self.test(value))
759 }
760
761 /// Returns a predicate that represents the logical NAND (NOT AND) of this
762 /// predicate and another.
763 ///
764 /// NAND returns `true` unless both predicates are `true`.
765 /// Equivalent to `!(self AND other)`.
766 ///
767 /// # Parameters
768 ///
769 /// * `other` - The other predicate to combine with. **Note: This parameter
770 /// is passed by value and will transfer ownership.** If you need to
771 /// preserve the original predicate, clone it first (if it implements
772 /// `Clone`). Accepts closures, function pointers, or any
773 /// `Predicate<T>` implementation.
774 ///
775 /// # Returns
776 ///
777 /// A `BoxPredicate` representing the logical NAND.
778 ///
779 /// # Examples
780 ///
781 /// ```rust
782 /// use qubit_function::predicate::{Predicate, FnPredicateOps};
783 ///
784 /// let is_positive = |x: &i32| *x > 0;
785 /// let is_even = |x: &i32| x % 2 == 0;
786 ///
787 /// let nand = is_positive.nand(is_even);
788 /// assert!(nand.test(&3)); // !(true && false) = true
789 /// assert!(!nand.test(&4)); // !(true && true) = false
790 /// ```
791 fn nand<P>(self, other: P) -> BoxPredicate<T>
792 where
793 Self: 'static,
794 P: Predicate<T> + 'static,
795 T: 'static,
796 {
797 BoxPredicate::new(move |value: &T| !(self.test(value) && other.test(value)))
798 }
799
800 /// Returns a predicate that represents the logical XOR (exclusive OR) of
801 /// this predicate and another.
802 ///
803 /// XOR returns `true` if exactly one of the predicates is `true`.
804 ///
805 /// # Parameters
806 ///
807 /// * `other` - The other predicate to combine with. **Note: This parameter
808 /// is passed by value and will transfer ownership.** If you need to
809 /// preserve the original predicate, clone it first (if it implements
810 /// `Clone`). Accepts closures, function pointers, or any
811 /// `Predicate<T>` implementation.
812 ///
813 /// # Returns
814 ///
815 /// A `BoxPredicate` representing the logical XOR.
816 ///
817 /// # Examples
818 ///
819 /// ```rust
820 /// use qubit_function::predicate::{Predicate, FnPredicateOps};
821 ///
822 /// let is_positive = |x: &i32| *x > 0;
823 /// let is_even = |x: &i32| x % 2 == 0;
824 ///
825 /// let xor = is_positive.xor(is_even);
826 /// assert!(xor.test(&3)); // true ^ false = true
827 /// assert!(!xor.test(&4)); // true ^ true = false
828 /// assert!(!xor.test(&-1)); // false ^ false = false
829 /// ```
830 fn xor<P>(self, other: P) -> BoxPredicate<T>
831 where
832 Self: 'static,
833 P: Predicate<T> + 'static,
834 T: 'static,
835 {
836 BoxPredicate::new(move |value: &T| self.test(value) ^ other.test(value))
837 }
838
839 /// Returns a predicate that represents the logical NOR (NOT OR) of this
840 /// predicate and another.
841 ///
842 /// NOR returns `true` only when both predicates are `false`. Equivalent
843 /// to `!(self OR other)`.
844 ///
845 /// # Parameters
846 ///
847 /// * `other` - The other predicate to combine with. **Note: This parameter
848 /// is passed by value and will transfer ownership.** If you need to
849 /// preserve the original predicate, clone it first (if it implements
850 /// `Clone`). Accepts closures, function pointers, or any
851 /// `Predicate<T>` implementation.
852 ///
853 /// # Returns
854 ///
855 /// A `BoxPredicate` representing the logical NOR.
856 ///
857 /// # Examples
858 ///
859 /// ```rust
860 /// use qubit_function::predicate::{Predicate, FnPredicateOps};
861 ///
862 /// let is_positive = |x: &i32| *x > 0;
863 /// let is_even = |x: &i32| x % 2 == 0;
864 ///
865 /// let nor = is_positive.nor(is_even);
866 /// assert!(nor.test(&-3)); // !(false || false) = true
867 /// assert!(!nor.test(&4)); // !(true || true) = false
868 /// assert!(!nor.test(&3)); // !(true || false) = false
869 /// ```
870 fn nor<P>(self, other: P) -> BoxPredicate<T>
871 where
872 Self: 'static,
873 P: Predicate<T> + 'static,
874 T: 'static,
875 {
876 BoxPredicate::new(move |value: &T| !(self.test(value) || other.test(value)))
877 }
878}
879
880// Blanket implementation for all closures
881impl<T, F> FnPredicateOps<T> for F where F: Fn(&T) -> bool {}