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§
Sourcefn and<P>(self, other: P) -> BoxPredicate<T>where
Self: 'static,
P: Predicate<T> + 'static,
T: 'static,
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 implementsClone). Can be:- Another closure
- A function pointer
- A
BoxPredicate<T>,RcPredicate<T>, orArcPredicate<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?
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
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}Sourcefn or<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,
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 implementsClone). Can be:- Another closure
- A function pointer
- A
BoxPredicate<T>,RcPredicate<T>, orArcPredicate<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));Sourcefn not(self) -> BoxPredicate<T>where
Self: 'static,
T: 'static,
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.
Sourcefn nand<P>(self, other: P) -> BoxPredicate<T>where
Self: 'static,
P: Predicate<T> + 'static,
T: 'static,
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 implementsClone). Accepts closures, function pointers, or anyPredicate<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) = falseSourcefn xor<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,
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 implementsClone). Accepts closures, function pointers, or anyPredicate<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 = falseSourcefn nor<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,
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 implementsClone). Accepts closures, function pointers, or anyPredicate<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) = falseDyn 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.