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