Skip to main content

FnPredicateOps

Trait FnPredicateOps 

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

fn or<P>(self, other: P) -> BoxPredicate<T>
where Self: 'static, 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 qubit_function::{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 Self: 'static, 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 Self: 'static, 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 qubit_function::{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 Self: 'static, 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 qubit_function::{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 Self: 'static, 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 qubit_function::{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,