Skip to main content

BoxConditionalMutator

Struct BoxConditionalMutator 

Source
pub struct BoxConditionalMutator<T> { /* private fields */ }
Expand description

BoxConditionalMutator struct

A conditional mutator that only executes when a predicate is satisfied. Uses BoxMutator and BoxPredicate for single ownership semantics.

This type is typically created by calling BoxMutator::when() and is designed to work with the or_else() method to create if-then-else logic.

§Features

  • Single Ownership: Not cloneable, consumes self on use
  • Conditional Execution: Only mutates when predicate returns true
  • Chainable: Can add or_else branch to create if-then-else logic
  • Implements Mutator: Can be used anywhere a Mutator is expected

§Examples

§Basic Conditional Execution

use qubit_function::{Mutator, BoxMutator};

let mutator = BoxMutator::new(|x: &mut i32| *x *= 2);
let mut conditional = mutator.when(|x: &i32| *x > 0);

let mut positive = 5;
conditional.apply(&mut positive);
assert_eq!(positive, 10); // Executed

let mut negative = -5;
conditional.apply(&mut negative);
assert_eq!(negative, -5); // Not executed

§With or_else Branch

use qubit_function::{Mutator, BoxMutator};

let mut mutator = BoxMutator::new(|x: &mut i32| *x *= 2)
    .when(|x: &i32| *x > 0)
    .or_else(|x: &mut i32| *x -= 1);

let mut positive = 5;
mutator.apply(&mut positive);
assert_eq!(positive, 10); // when branch executed

let mut negative = -5;
mutator.apply(&mut negative);
assert_eq!(negative, -6); // or_else branch executed

Implementations§

Source§

impl<T> BoxConditionalMutator<T>

Source

pub fn and_then<M>(self, next: M) -> BoxMutator<T>
where T: 'static, M: Mutator<T> + 'static,

Chains another mutator in sequence

Combines the current conditional mutator with another mutator into a new mutator that implements the following semantics:

When the returned mutator is called with an argument:

  1. First, it checks the predicate of this conditional mutator
  2. If the predicate is satisfied, it executes the internal mutator of this conditional mutator
  3. Then, regardless of whether the predicate was satisfied, it unconditionally executes the next mutator

In other words, this creates a mutator that conditionally executes the first action (based on the predicate), and then always executes the second action.

§Parameters
  • next - The next mutator to execute (always executed)
§Returns

Returns a new combined mutator

§Examples
// use std::sync::atomic::{AtomicI32, Ordering};
//
// let result = AtomicI32::new(0);
//
// let mutator1 = BoxMutator::new(|x: &mut i32| {
//     *x += 1;
// });
//
// let mutator2 = BoxMutator::new(|x: &mut i32| {
//     *x += 2;
// });
//
// let conditional = mutator1.when(|x| *x > 0);
// let chained = conditional.and_then(mutator2);
//
// let mut val = 5;
// chained.apply(&mut val);  // val = 5 + 1 + 2 = 8
// let mut val2 = -1;
// chained.apply(&mut val2); // val2 = -1 + 2 = 1 (not -1 + 1 + 2!)
// ```
Source

pub fn or_else<M>(self, else_mutator: M) -> BoxMutator<T>
where T: 'static, M: Mutator<T> + 'static,

Adds an else branch

Executes the original mutator when the condition is satisfied, otherwise executes else_mutator.

§Parameters
  • else_mutator - The mutator for the else branch
§Returns

Returns a new mutator with if-then-else logic

Examples found in repository?
examples/mutators/mutator_demo.rs (line 110)
27fn main() {
28    println!("=== Mutator Demo ===\n");
29
30    // ========================================================================
31    // Example 1: BoxMutator Basic Usage
32    // ========================================================================
33    println!("Example 1: BoxMutator Basic Usage");
34    println!("{}", "-".repeat(50));
35
36    let mutator = BoxMutator::new(|x: &mut i32| {
37        *x *= 2;
38    });
39    let mut value = 5;
40    println!("Initial value: {}", value);
41    mutator.apply(&mut value);
42    println!("After BoxMutator execution: {}\n", value);
43
44    // ========================================================================
45    // Example 2: BoxMutator Method Chaining
46    // ========================================================================
47    println!("Example 2: BoxMutator Method Chaining");
48    println!("{}", "-".repeat(50));
49
50    let chained = BoxMutator::new(|x: &mut i32| {
51        *x *= 2; // multiply by 2
52    })
53    .and_then(|x: &mut i32| {
54        *x += 10; // add 10
55    })
56    .and_then(|x: &mut i32| {
57        *x = *x * *x; // square
58    });
59
60    let mut value = 5;
61    println!("Initial value: {}", value);
62    chained.apply(&mut value);
63    println!("Result: {} (5 * 2 + 10 = 20, 20 * 20 = 400)\n", value);
64
65    // ========================================================================
66    // Example 3: Closure Extension Methods
67    // ========================================================================
68    println!("Example 3: Direct Use of Closure Extension Methods");
69    println!("{}", "-".repeat(50));
70
71    let closure_chain = (|x: &mut i32| *x *= 2).and_then(|x: &mut i32| *x += 10);
72
73    let mut value = 5;
74    println!("Initial value: {}", value);
75    closure_chain.apply(&mut value);
76    println!("Result: {} (5 * 2 + 10 = 20)\n", value);
77
78    // ========================================================================
79    // Example 4: BoxMutator Factory Methods
80    // ========================================================================
81    println!("Example 4: BoxMutator Factory Methods");
82    println!("{}", "-".repeat(50));
83
84    // noop
85    let noop = BoxMutator::<i32>::noop();
86    let mut value = 42;
87    println!("Before noop: {}", value);
88    noop.apply(&mut value);
89    println!("After noop: {} (unchanged)\n", value);
90
91    // ========================================================================
92    // Example 5: Conditional Mutator
93    // ========================================================================
94    println!("Example 5: Conditional Mutator");
95    println!("{}", "-".repeat(50));
96
97    // when (conditional execution)
98    let increment_if_positive = BoxMutator::new(|x: &mut i32| *x += 1).when(|x: &i32| *x > 0);
99
100    let mut positive = 5;
101    let mut negative = -5;
102    println!("Before when - positive: {}, negative: {}", positive, negative);
103    increment_if_positive.apply(&mut positive);
104    increment_if_positive.apply(&mut negative);
105    println!("After when - positive: {}, negative: {}\n", positive, negative);
106
107    // when().or_else() (conditional branching)
108    let adjust = BoxMutator::new(|x: &mut i32| *x *= 2)
109        .when(|x: &i32| *x > 0)
110        .or_else(|x: &mut i32| *x = -*x);
111
112    let mut positive = 10;
113    let mut negative = -10;
114    println!(
115        "Before when().or_else() - positive: {}, negative: {}",
116        positive, negative
117    );
118    adjust.apply(&mut positive);
119    adjust.apply(&mut negative);
120    println!(
121        "After when().or_else() - positive: {}, negative: {}\n",
122        positive, negative
123    );
124
125    // ========================================================================
126    // Example 6: ArcMutator - Multi-threaded Sharing
127    // ========================================================================
128    println!("Example 6: ArcMutator - Multi-threaded Sharing");
129    println!("{}", "-".repeat(50));
130
131    let shared = ArcMutator::new(|x: &mut i32| *x *= 2);
132
133    // Clone for another thread
134    let shared_clone = shared.clone();
135    let handle = thread::spawn(move || {
136        let mut value = 5;
137        let mutator = shared_clone;
138        mutator.apply(&mut value);
139        println!("In thread: 5 * 2 = {}", value);
140        value
141    });
142
143    // Use in main thread
144    let mut value = 3;
145    let mutator = shared;
146    mutator.apply(&mut value);
147    println!("Main thread: 3 * 2 = {}", value);
148
149    let thread_result = handle.join().expect("thread should not panic");
150    println!("Thread result: {}\n", thread_result);
151
152    // ========================================================================
153    // Example 7: ArcMutator Composition (without consuming original mutator)
154    // ========================================================================
155    println!("Example 7: ArcMutator Composition (borrowing &self)");
156    println!("{}", "-".repeat(50));
157
158    let double = ArcMutator::new(|x: &mut i32| *x *= 2);
159    let add_ten = ArcMutator::new(|x: &mut i32| *x += 10);
160
161    // Composition doesn't consume the original mutator
162    let pipeline1 = double.and_then(add_ten.clone());
163    let pipeline2 = add_ten.and_then(double.clone());
164
165    let mut value1 = 5;
166    let p1 = pipeline1;
167    p1.apply(&mut value1);
168    println!("pipeline1 (double then add): 5 -> {}", value1);
169
170    let mut value2 = 5;
171    let p2 = pipeline2;
172    p2.apply(&mut value2);
173    println!("pipeline2 (add then double): 5 -> {}", value2);
174
175    // double and add_ten are still available
176    let mut value3 = 10;
177    let d = double;
178    d.apply(&mut value3);
179    println!("Original double still available: 10 -> {}\n", value3);
180
181    // ========================================================================
182    // Example 8: RcMutator - Single-threaded Sharing
183    // ========================================================================
184    println!("Example 8: RcMutator - Single-threaded Sharing");
185    println!("{}", "-".repeat(50));
186
187    let rc_mutator = RcMutator::new(|x: &mut i32| *x *= 2);
188
189    // Clone multiple copies
190    let clone1 = rc_mutator.clone();
191    let clone2 = rc_mutator.clone();
192
193    let mut value1 = 5;
194    let c1 = clone1;
195    c1.apply(&mut value1);
196    println!("clone1: 5 -> {}", value1);
197
198    let mut value2 = 3;
199    let c2 = clone2;
200    c2.apply(&mut value2);
201    println!("clone2: 3 -> {}", value2);
202
203    let mut value3 = 7;
204    let c3 = rc_mutator;
205    c3.apply(&mut value3);
206    println!("Original: 7 -> {}\n", value3);
207
208    // ========================================================================
209    // Example 9: RcMutator Composition (borrowing &self)
210    // ========================================================================
211    println!("Example 9: RcMutator Composition (borrowing &self)");
212    println!("{}", "-".repeat(50));
213
214    let double = RcMutator::new(|x: &mut i32| *x *= 2);
215    let add_ten = RcMutator::new(|x: &mut i32| *x += 10);
216
217    let pipeline1 = double.and_then(add_ten.clone());
218    let pipeline2 = add_ten.and_then(double.clone());
219
220    let mut value1 = 5;
221    let p1 = pipeline1;
222    p1.apply(&mut value1);
223    println!("pipeline1 (double then add): 5 -> {}", value1);
224
225    let mut value2 = 5;
226    let p2 = pipeline2;
227    p2.apply(&mut value2);
228    println!("pipeline2 (add then double): 5 -> {}\n", value2);
229
230    // ========================================================================
231    // Example 10: Unified Mutator trait
232    // ========================================================================
233    println!("Example 10: Unified Mutator trait");
234    println!("{}", "-".repeat(50));
235
236    fn apply_to_all<M: Mutator<i32>>(mutator: &mut M, values: &mut [i32]) {
237        for value in values.iter_mut() {
238            mutator.apply(value);
239        }
240    }
241
242    let mut values1 = vec![1, 2, 3, 4, 5];
243    let mut box_mut = BoxMutator::new(|x: &mut i32| *x *= 2);
244    println!("Using BoxMutator: {:?}", values1);
245    apply_to_all(&mut box_mut, &mut values1);
246    println!("Result: {:?}", values1);
247
248    let mut values2 = vec![1, 2, 3, 4, 5];
249    let mut arc_mut = ArcMutator::new(|x: &mut i32| *x *= 2);
250    println!("Using ArcMutator: {:?}", values2);
251    apply_to_all(&mut arc_mut, &mut values2);
252    println!("Result: {:?}", values2);
253
254    let mut values3 = vec![1, 2, 3, 4, 5];
255    let mut rc_mut = RcMutator::new(|x: &mut i32| *x *= 2);
256    println!("Using RcMutator: {:?}", values3);
257    apply_to_all(&mut rc_mut, &mut values3);
258    println!("Result: {:?}", values3);
259
260    let mut values4 = vec![1, 2, 3, 4, 5];
261    let mut closure = |x: &mut i32| *x *= 2;
262    println!("Using closure: {:?}", values4);
263    apply_to_all(&mut closure, &mut values4);
264    println!("Result: {:?}\n", values4);
265
266    // ========================================================================
267    // Example 11: Complex Data Processing Pipeline
268    // ========================================================================
269    println!("Example 11: Complex Data Processing Pipeline");
270    println!("{}", "-".repeat(50));
271
272    let pipeline = BoxMutator::new(|x: &mut i32| {
273        // Validation: clamp to 0-100
274        *x = (*x).clamp(0, 100);
275    })
276    .and_then(|x: &mut i32| {
277        // Normalization: scale to 0-10
278        *x /= 10;
279    })
280    .and_then(|x: &mut i32| {
281        // Transformation: square
282        *x = *x * *x;
283    });
284
285    let mut value1 = -50;
286    pipeline.apply(&mut value1);
287    println!("-50 -> {}", value1);
288
289    let mut value2 = 200;
290    pipeline.apply(&mut value2);
291    println!("200 -> {}", value2);
292
293    let mut value3 = 30;
294    pipeline.apply(&mut value3);
295    println!("30 -> {}\n", value3);
296
297    // ========================================================================
298    // Example 12: String Processing
299    // ========================================================================
300    println!("Example 12: String Processing");
301    println!("{}", "-".repeat(50));
302
303    let string_processor = BoxMutator::new(|s: &mut String| s.retain(|c| !c.is_whitespace()))
304        .and_then(|s: &mut String| *s = s.to_lowercase())
305        .and_then(|s: &mut String| s.push_str("!!!"));
306
307    let mut text = String::from("Hello World");
308    println!("Original: {}", text);
309    string_processor.apply(&mut text);
310    println!("After processing: {}\n", text);
311
312    // ========================================================================
313    // Example 13: Type Conversion
314    // ========================================================================
315    println!("Example 13: Type Conversion");
316    println!("{}", "-".repeat(50));
317
318    // Closure -> BoxMutator
319    let closure = |x: &mut i32| *x *= 2;
320    let box_mut = closure.into_box();
321    let mut value = 5;
322    box_mut.apply(&mut value);
323    println!("Closure -> BoxMutator: 5 -> {}", value);
324
325    // Closure -> RcMutator
326    let closure = |x: &mut i32| *x *= 2;
327    let rc_mut = closure.into_rc();
328    let mut value = 5;
329    rc_mut.apply(&mut value);
330    println!("Closure -> RcMutator: 5 -> {}", value);
331
332    // Closure -> ArcMutator
333    let closure = |x: &mut i32| *x *= 2;
334    let arc_mut = closure.into_arc();
335    let mut value = 5;
336    arc_mut.apply(&mut value);
337    println!("Closure -> ArcMutator: 5 -> {}", value);
338
339    // BoxMutator -> RcMutator
340    let box_mut = BoxMutator::new(|x: &mut i32| *x *= 2);
341    let rc_mut = box_mut.into_rc();
342    let mut value = 5;
343    rc_mut.apply(&mut value);
344    println!("BoxMutator -> RcMutator: 5 -> {}", value);
345
346    // RcMutator -> BoxMutator
347    let rc_mut = RcMutator::new(|x: &mut i32| *x *= 2);
348    let box_mut = rc_mut.into_box();
349    let mut value = 5;
350    box_mut.apply(&mut value);
351    println!("RcMutator -> BoxMutator: 5 -> {}\n", value);
352
353    // ========================================================================
354    // Example 14: Custom Types
355    // ========================================================================
356    println!("Example 14: Custom Types");
357    println!("{}", "-".repeat(50));
358
359    #[derive(Debug, Clone)]
360    struct Point {
361        x: i32,
362        y: i32,
363    }
364
365    let processor = BoxMutator::new(|p: &mut Point| p.x *= 2)
366        .and_then(|p: &mut Point| p.y *= 2)
367        .and_then(|p: &mut Point| p.x += p.y);
368
369    let mut point = Point { x: 3, y: 4 };
370    println!("Original point: {:?}", point);
371    processor.apply(&mut point);
372    println!("After processing: {:?}\n", point);
373
374    println!("=== All Examples Completed ===");
375}

Trait Implementations§

Source§

impl<T> Debug for BoxConditionalMutator<T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T> Display for BoxConditionalMutator<T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T> Mutator<T> for BoxConditionalMutator<T>

Source§

fn apply(&self, value: &mut T)

Performs the stateless mutation operation Read more
Source§

fn into_box(self) -> BoxMutator<T>
where Self: 'static,

Convert this mutator into a BoxMutator<T>. Read more
Source§

fn into_rc(self) -> RcMutator<T>
where Self: 'static,

Convert this mutator into an RcMutator<T>. Read more
Source§

fn into_fn(self) -> impl Fn(&mut T)

Consume the mutator and return an Fn(&mut T) closure. Read more
Source§

fn into_arc(self) -> ArcMutator<T>
where Self: Sized + Send + Sync + 'static,

Convert this mutator into an ArcMutator<T>. Read more
Source§

fn into_once(self) -> BoxMutatorOnce<T>
where Self: Sized + 'static,

Convert this mutator into a BoxMutatorOnce<T> (consuming). Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.