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));

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