FnPredicateOps

Trait FnPredicateOps 

Source
pub trait FnPredicateOps<T>:
    Fn(&T) -> bool
    + Sized
    + 'static {
    // Provided methods
    fn and<P>(self, other: P) -> BoxPredicate<T>
       where P: Predicate<T> + 'static,
             T: 'static { ... }
    fn or<P>(self, other: P) -> BoxPredicate<T>
       where P: Predicate<T> + 'static,
             T: 'static { ... }
    fn not(self) -> BoxPredicate<T>
       where T: 'static { ... }
    fn nand<P>(self, other: P) -> BoxPredicate<T>
       where P: Predicate<T> + 'static,
             T: 'static { ... }
    fn xor<P>(self, other: P) -> BoxPredicate<T>
       where P: Predicate<T> + 'static,
             T: 'static { ... }
    fn nor<P>(self, other: P) -> BoxPredicate<T>
       where P: Predicate<T> + 'static,
             T: 'static { ... }
}
Expand description

Extension trait providing logical composition methods for closures.

This trait is automatically implemented for all closures and function pointers that match Fn(&T) -> bool, enabling method chaining starting from a closure.

§Examples

use prism3_function::predicate::{Predicate, FnPredicateOps};

let is_positive = |x: &i32| *x > 0;
let is_even = |x: &i32| x % 2 == 0;

// Combine predicates using extension methods
let pred = is_positive.and(is_even);
assert!(pred.test(&4));
assert!(!pred.test(&3));

§Author

Haixing Hu

Provided Methods§

Source

fn and<P>(self, other: P) -> BoxPredicate<T>
where P: Predicate<T> + 'static, T: 'static,

Returns a predicate that represents the logical AND of this predicate and another.

§Parameters
  • other - The other predicate to combine with. Note: This parameter is passed by value and will transfer ownership. If you need to preserve the original predicate, clone it first (if it implements Clone). Can be:
    • Another closure
    • A function pointer
    • A BoxPredicate<T>, RcPredicate<T>, or ArcPredicate<T>
§Returns

A BoxPredicate representing the logical AND.

§Examples
use prism3_function::predicate::{Predicate, FnPredicateOps};

let is_positive = |x: &i32| *x > 0;
let is_even = |x: &i32| x % 2 == 0;

let combined = is_positive.and(is_even);
assert!(combined.test(&4));
assert!(!combined.test(&3));
Examples found in repository?
examples/predicate_demo.rs (line 63)
53fn basic_closure_predicates() {
54    println!("--- 1. Basic Closure Predicate Usage ---");
55
56    // Simple closure predicate
57    let is_positive = |x: &i32| *x > 0;
58    println!("Is 5 positive? {}", is_positive.test(&5));
59    println!("Is -3 positive? {}", is_positive.test(&-3));
60
61    // Combining closures
62    let is_even = |x: &i32| x % 2 == 0;
63    let is_positive_and_even = is_positive.and(is_even);
64    println!("Is 4 positive and even? {}", is_positive_and_even.test(&4));
65    println!("Is 5 positive and even? {}", is_positive_and_even.test(&5));
66
67    // Using predicates with iterators
68    let numbers = [-2, -1, 0, 1, 2, 3, 4, 5];
69    let positives: Vec<_> = numbers
70        .iter()
71        .filter(|x| is_positive.test(x))
72        .copied()
73        .collect();
74    println!("Positive numbers: {:?}", positives);
75}
More examples
Hide additional examples
examples/mutator_once_conditional_demo.rs (lines 77-80)
16fn main() {
17    println!("=== MutatorOnce Conditional Execution Examples ===\n");
18
19    // 1. Basic conditional execution - when condition is satisfied
20    println!("1. Basic conditional execution - when condition is satisfied");
21    let data = vec![1, 2, 3];
22    let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
23        println!("   Extending vector with data: {:?}", data);
24        x.extend(data);
25    });
26    let conditional = mutator.when(|x: &Vec<i32>| {
27        println!("   Checking condition: !x.is_empty()");
28        !x.is_empty()
29    });
30
31    let mut target = vec![0];
32    println!("   Initial: {:?}", target);
33    conditional.mutate_once(&mut target);
34    println!("   Result: {:?}\n", target);
35
36    // 2. Conditional execution - when condition is not satisfied
37    println!("2. Conditional execution - when condition is not satisfied");
38    let data = vec![4, 5, 6];
39    let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
40        println!("   This should not be executed");
41        x.extend(data);
42    });
43    let conditional = mutator.when(|x: &Vec<i32>| {
44        println!("   Checking condition: x.len() > 10");
45        x.len() > 10
46    });
47
48    let mut target = vec![0];
49    println!("   Initial: {:?}", target);
50    conditional.mutate_once(&mut target);
51    println!("   Result: {:?} (unchanged)\n", target);
52
53    // 3. Using BoxPredicate
54    println!("3. Using BoxPredicate");
55    let pred = BoxPredicate::new(|x: &Vec<i32>| {
56        println!("   Predicate: checking if vector is not empty");
57        !x.is_empty()
58    });
59    let data = vec![7, 8, 9];
60    let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
61        println!("   Adding data: {:?}", data);
62        x.extend(data);
63    });
64    let conditional = mutator.when(pred);
65
66    let mut target = vec![0];
67    println!("   Initial: {:?}", target);
68    conditional.mutate_once(&mut target);
69    println!("   Result: {:?}\n", target);
70
71    // 4. Using composed predicate
72    println!("4. Using composed predicate");
73    let pred = (|x: &Vec<i32>| {
74        println!("   Condition 1: !x.is_empty()");
75        !x.is_empty()
76    })
77    .and(|x: &Vec<i32>| {
78        println!("   Condition 2: x.len() < 10");
79        x.len() < 10
80    });
81    let data = vec![10, 11, 12];
82    let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
83        println!("   Adding data: {:?}", data);
84        x.extend(data);
85    });
86    let conditional = mutator.when(pred);
87
88    let mut target = vec![0];
89    println!("   Initial: {:?}", target);
90    conditional.mutate_once(&mut target);
91    println!("   Result: {:?}\n", target);
92
93    // 5. If-then-else with or_else - when branch
94    println!("5. If-then-else with or_else - when branch");
95    let data1 = vec![1, 2, 3];
96    let data2 = vec![99];
97    let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
98        println!("   When branch: adding {:?}", data1);
99        x.extend(data1);
100    })
101    .when(|x: &Vec<i32>| {
102        println!("   Checking: !x.is_empty()");
103        !x.is_empty()
104    })
105    .or_else(move |x: &mut Vec<i32>| {
106        println!("   Else branch: adding {:?}", data2);
107        x.extend(data2);
108    });
109
110    let mut target = vec![0];
111    println!("   Initial: {:?}", target);
112    mutator.mutate_once(&mut target);
113    println!("   Result: {:?}\n", target);
114
115    // 6. If-then-else with or_else - else branch
116    println!("6. If-then-else with or_else - else branch");
117    let data1 = vec![4, 5, 6];
118    let data2 = vec![99];
119    let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
120        println!("   When branch: adding {:?}", data1);
121        x.extend(data1);
122    })
123    .when(|x: &Vec<i32>| {
124        println!("   Checking: x.is_empty()");
125        x.is_empty()
126    })
127    .or_else(move |x: &mut Vec<i32>| {
128        println!("   Else branch: adding {:?}", data2);
129        x.extend(data2);
130    });
131
132    let mut target = vec![0];
133    println!("   Initial: {:?}", target);
134    mutator.mutate_once(&mut target);
135    println!("   Result: {:?}\n", target);
136
137    // 7. Conditional with integers
138    println!("7. Conditional with integers");
139    let mutator = BoxMutatorOnce::new(|x: &mut i32| {
140        println!("   Multiplying by 2");
141        *x *= 2;
142    })
143    .when(|x: &i32| {
144        println!("   Checking: *x > 0");
145        *x > 0
146    });
147
148    let mut positive = 5;
149    println!("   Initial (positive): {}", positive);
150    mutator.mutate_once(&mut positive);
151    println!("   Result: {}\n", positive);
152
153    // 8. Conditional with integers - not executed
154    println!("8. Conditional with integers - not executed");
155    let mutator = BoxMutatorOnce::new(|x: &mut i32| {
156        println!("   This should not be executed");
157        *x *= 2;
158    })
159    .when(|x: &i32| {
160        println!("   Checking: *x > 0");
161        *x > 0
162    });
163
164    let mut negative = -5;
165    println!("   Initial (negative): {}", negative);
166    mutator.mutate_once(&mut negative);
167    println!("   Result: {} (unchanged)\n", negative);
168
169    // 9. Chaining conditional mutators
170    println!("9. Chaining conditional mutators");
171    let data1 = vec![1, 2];
172    let cond1 = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
173        println!("   First mutator: adding {:?}", data1);
174        x.extend(data1);
175    })
176    .when(|x: &Vec<i32>| {
177        println!("   First condition: !x.is_empty()");
178        !x.is_empty()
179    });
180
181    let data2 = vec![3, 4];
182    let cond2 = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
183        println!("   Second mutator: adding {:?}", data2);
184        x.extend(data2);
185    })
186    .when(|x: &Vec<i32>| {
187        println!("   Second condition: x.len() < 10");
188        x.len() < 10
189    });
190
191    let chained = cond1.and_then(cond2);
192
193    let mut target = vec![0];
194    println!("   Initial: {:?}", target);
195    chained.mutate_once(&mut target);
196    println!("   Result: {:?}\n", target);
197
198    // 10. Complex conditional chain
199    println!("10. Complex conditional chain");
200    let data1 = vec![1, 2];
201    let data2 = vec![99];
202    let data3 = vec![5, 6];
203
204    let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
205        println!("   When branch: adding {:?}", data1);
206        x.extend(data1);
207    })
208    .when(|x: &Vec<i32>| {
209        println!("   Checking: !x.is_empty()");
210        !x.is_empty()
211    })
212    .or_else(move |x: &mut Vec<i32>| {
213        println!("   Else branch: adding {:?}", data2);
214        x.extend(data2);
215    })
216    .and_then(move |x: &mut Vec<i32>| {
217        println!("   Final step: adding {:?}", data3);
218        x.extend(data3);
219    });
220
221    let mut target = vec![0];
222    println!("   Initial: {:?}", target);
223    mutator.mutate_once(&mut target);
224    println!("   Result: {:?}\n", target);
225
226    // 11. Real-world scenario: data validation and processing
227    println!("11. Real-world scenario: data validation and processing");
228
229    struct DataProcessor {
230        on_valid: Option<BoxMutatorOnce<Vec<String>>>,
231        on_invalid: Option<BoxMutatorOnce<Vec<String>>>,
232    }
233
234    impl DataProcessor {
235        fn new<V, I>(on_valid: V, on_invalid: I) -> Self
236        where
237            V: FnOnce(&mut Vec<String>) + 'static,
238            I: FnOnce(&mut Vec<String>) + 'static,
239        {
240            Self {
241                on_valid: Some(BoxMutatorOnce::new(on_valid)),
242                on_invalid: Some(BoxMutatorOnce::new(on_invalid)),
243            }
244        }
245
246        fn process(mut self, data: &mut Vec<String>) {
247            let is_valid = !data.is_empty() && data.iter().all(|s| !s.is_empty());
248            println!(
249                "   Data validation: {}",
250                if is_valid { "VALID" } else { "INVALID" }
251            );
252
253            if is_valid {
254                if let Some(callback) = self.on_valid.take() {
255                    callback.mutate_once(data);
256                }
257            } else if let Some(callback) = self.on_invalid.take() {
258                callback.mutate_once(data);
259            }
260        }
261    }
262
263    let valid_suffix = vec!["processed".to_string()];
264    let invalid_marker = vec!["[INVALID]".to_string()];
265
266    let processor = DataProcessor::new(
267        move |data| {
268            println!("   Valid data callback: adding suffix");
269            data.extend(valid_suffix);
270        },
271        move |data| {
272            println!("   Invalid data callback: adding error marker");
273            data.clear();
274            data.extend(invalid_marker);
275        },
276    );
277
278    let mut valid_data = vec!["item1".to_string(), "item2".to_string()];
279    println!("   Processing valid data: {:?}", valid_data);
280    processor.process(&mut valid_data);
281    println!("   Result: {:?}\n", valid_data);
282
283    println!("=== Examples completed ===");
284}
Source

fn or<P>(self, other: P) -> BoxPredicate<T>
where P: Predicate<T> + 'static, T: 'static,

Returns a predicate that represents the logical OR of this predicate and another.

§Parameters
  • other - The other predicate to combine with. Note: This parameter is passed by value and will transfer ownership. If you need to preserve the original predicate, clone it first (if it implements Clone). Can be:
    • Another closure
    • A function pointer
    • A BoxPredicate<T>, RcPredicate<T>, or ArcPredicate<T>
    • Any type implementing Predicate<T>
§Returns

A BoxPredicate representing the logical OR.

§Examples
use prism3_function::predicate::{Predicate, FnPredicateOps};

let is_negative = |x: &i32| *x < 0;
let is_large = |x: &i32| *x > 100;

let combined = is_negative.or(is_large);
assert!(combined.test(&-5));
assert!(combined.test(&150));
assert!(!combined.test(&50));
Source

fn not(self) -> BoxPredicate<T>
where T: 'static,

Returns a predicate that represents the logical negation of this predicate.

§Returns

A BoxPredicate representing the logical negation.

Source

fn nand<P>(self, other: P) -> BoxPredicate<T>
where P: Predicate<T> + 'static, T: 'static,

Returns a predicate that represents the logical NAND (NOT AND) of this predicate and another.

NAND returns true unless both predicates are true. Equivalent to !(self AND other).

§Parameters
  • other - The other predicate to combine with. Note: This parameter is passed by value and will transfer ownership. If you need to preserve the original predicate, clone it first (if it implements Clone). Accepts closures, function pointers, or any Predicate<T> implementation.
§Returns

A BoxPredicate representing the logical NAND.

§Examples
use prism3_function::predicate::{Predicate, FnPredicateOps};

let is_positive = |x: &i32| *x > 0;
let is_even = |x: &i32| x % 2 == 0;

let nand = is_positive.nand(is_even);
assert!(nand.test(&3));   // !(true && false) = true
assert!(!nand.test(&4));  // !(true && true) = false
Source

fn xor<P>(self, other: P) -> BoxPredicate<T>
where P: Predicate<T> + 'static, T: 'static,

Returns a predicate that represents the logical XOR (exclusive OR) of this predicate and another.

XOR returns true if exactly one of the predicates is true.

§Parameters
  • other - The other predicate to combine with. Note: This parameter is passed by value and will transfer ownership. If you need to preserve the original predicate, clone it first (if it implements Clone). Accepts closures, function pointers, or any Predicate<T> implementation.
§Returns

A BoxPredicate representing the logical XOR.

§Examples
use prism3_function::predicate::{Predicate, FnPredicateOps};

let is_positive = |x: &i32| *x > 0;
let is_even = |x: &i32| x % 2 == 0;

let xor = is_positive.xor(is_even);
assert!(xor.test(&3));    // true ^ false = true
assert!(!xor.test(&4));   // true ^ true = false
assert!(!xor.test(&-1));  // false ^ false = false
Source

fn nor<P>(self, other: P) -> BoxPredicate<T>
where P: Predicate<T> + 'static, T: 'static,

Returns a predicate that represents the logical NOR (NOT OR) of this predicate and another.

NOR returns true only when both predicates are false. Equivalent to !(self OR other).

§Parameters
  • other - The other predicate to combine with. Note: This parameter is passed by value and will transfer ownership. If you need to preserve the original predicate, clone it first (if it implements Clone). Accepts closures, function pointers, or any Predicate<T> implementation.
§Returns

A BoxPredicate representing the logical NOR.

§Examples
use prism3_function::predicate::{Predicate, FnPredicateOps};

let is_positive = |x: &i32| *x > 0;
let is_even = |x: &i32| x % 2 == 0;

let nor = is_positive.nor(is_even);
assert!(nor.test(&-3));   // !(false || false) = true
assert!(!nor.test(&4));   // !(true || true) = false
assert!(!nor.test(&3));   // !(true || false) = false

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§

Source§

impl<T, F> FnPredicateOps<T> for F
where F: Fn(&T) -> bool + 'static,