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 prism3_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.mutate(&mut positive);
assert_eq!(positive, 10); // Executed

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

§With or_else Branch

use prism3_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.mutate(&mut positive);
assert_eq!(positive, 10); // when branch executed

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

§Author

Haixing Hu

Implementations§

Source§

impl<T> BoxConditionalMutator<T>
where T: 'static,

Source

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

Chains another mutator in sequence

Combines the current conditional mutator with another mutator into a new mutator. The current conditional mutator executes first, followed by the next mutator.

§Parameters
  • next - The next mutator to execute. Note: This parameter is passed by value and will transfer ownership. If you need to preserve the original mutator, clone it first (if it implements Clone). Can be:
    • A closure: |x: &mut T|
    • A BoxMutator<T>
    • An ArcMutator<T>
    • An RcMutator<T>
    • Any type implementing Mutator<T>
§Returns

Returns a new BoxMutator<T>

§Examples
§Direct value passing (ownership transfer)
use prism3_function::{Mutator, BoxMutator};

let cond1 = BoxMutator::new(|x: &mut i32| *x *= 2).when(|x: &i32| *x > 0);
let cond2 = BoxMutator::new(|x: &mut i32| *x = 100).when(|x: &i32| *x > 100);

// cond2 is moved here
let mut chained = cond1.and_then(cond2);
let mut value = 60;
chained.mutate(&mut value);
assert_eq!(value, 100); // First *2 = 120, then capped to 100
// cond2.mutate(&mut value); // Would not compile - moved
§Preserving original with clone
use prism3_function::{Mutator, BoxMutator};

let cond1 = BoxMutator::new(|x: &mut i32| *x *= 2).when(|x: &i32| *x > 0);
let cond2 = BoxMutator::new(|x: &mut i32| *x = 100).when(|x: &i32| *x > 100);

// Clone to preserve original
let mut chained = cond1.and_then(cond2.clone());
let mut value = 60;
chained.mutate(&mut value);
assert_eq!(value, 100); // First *2 = 120, then capped to 100

// Original still usable
let mut value2 = 50;
cond2.mutate(&mut value2);
assert_eq!(value2, 100);
Source

pub fn or_else<C>(self, else_mutator: C) -> BoxMutator<T>
where C: 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. Note: This parameter is passed by value and will transfer ownership. If you need to preserve the original mutator, clone it first (if it implements Clone). Can be:
    • A closure: |x: &mut T|
    • A BoxMutator<T>
    • An RcMutator<T>
    • An ArcMutator<T>
    • Any type implementing Mutator<T>
§Returns

Returns the composed BoxMutator<T>

§Examples
use prism3_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.mutate(&mut positive);
assert_eq!(positive, 10); // Condition satisfied, execute *2

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

Trait Implementations§

Source§

impl<T> Mutator<T> for BoxConditionalMutator<T>
where T: 'static,

Source§

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

Performs the mutation operation Read more
Source§

fn into_box(self) -> BoxMutator<T>

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

fn into_rc(self) -> RcMutator<T>

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

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

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

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

Convert this mutator into an ArcMutator<T>. 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, 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.