Module mutator

Module mutator 

Source
Expand description

§Mutator Types

Provides Java-like Mutator interface implementations for performing operations that accept a single mutable input parameter and return no result.

This module provides a unified Mutator trait and three concrete implementations based on different ownership models:

  • BoxMutator<T>: Box-based single ownership implementation for one-time use scenarios and builder patterns
  • ArcMutator<T>: Arc<Mutex<>>-based thread-safe shared ownership implementation for multi-threaded scenarios
  • RcMutator<T>: Rc<RefCell<>>-based single-threaded shared ownership implementation with no lock overhead

§Design Philosophy

Unlike Consumer which observes values without modifying them (FnMut(&T)), Mutator is designed to modify input values using FnMut(&mut T).

§Mutator vs Consumer

TypeInputModifies Input?Modifies Self?Use Cases
Consumer&TObserve, log, count, notify
Mutator&mut TModify, transform, update

Key Insight: If you need to modify input values, use Mutator. If you only need to observe or accumulate state, use Consumer.

§Comparison Table

FeatureBoxMutatorArcMutatorRcMutator
OwnershipSingleSharedShared
Cloneable
Thread-Safe
Interior Mut.N/AMutexRefCell
and_then APIself&self&self
Lock OverheadNoneYesNone

§Use Cases

§BoxMutator

  • One-time operations that don’t require sharing
  • Builder patterns where ownership naturally flows
  • Simple scenarios with no reuse requirements

§ArcMutator

  • Multi-threaded shared operations
  • Concurrent task processing (e.g., thread pools)
  • Situations requiring the same mutator across threads

§RcMutator

  • Single-threaded operations with multiple uses
  • Event handling in single-threaded UI frameworks
  • Performance-critical single-threaded scenarios

§Examples

§Basic Usage

use prism3_function::{BoxMutator, ArcMutator, RcMutator, Mutator};

// BoxMutator: Single ownership, consumes self
let mut mutator = BoxMutator::new(|x: &mut i32| *x *= 2);
let mut value = 5;
mutator.mutate(&mut value);
assert_eq!(value, 10);

// ArcMutator: Shared ownership, cloneable, thread-safe
let shared = ArcMutator::new(|x: &mut i32| *x *= 2);
let clone = shared.clone();
let mut value = 5;
let mut m = shared;
m.mutate(&mut value);
assert_eq!(value, 10);

// RcMutator: Shared ownership, cloneable, single-threaded
let rc = RcMutator::new(|x: &mut i32| *x *= 2);
let clone = rc.clone();
let mut value = 5;
let mut m = rc;
m.mutate(&mut value);
assert_eq!(value, 10);

§Method Chaining

use prism3_function::{Mutator, BoxMutator, ArcMutator};

// BoxMutator: Consumes self
let mut chained = BoxMutator::new(|x: &mut i32| *x *= 2)
    .and_then(|x: &mut i32| *x += 10);
let mut value = 5;
chained.mutate(&mut value);
assert_eq!(value, 20); // (5 * 2) + 10

// ArcMutator: Borrows &self, original still usable
let first = ArcMutator::new(|x: &mut i32| *x *= 2);
let second = ArcMutator::new(|x: &mut i32| *x += 10);
let combined = first.and_then(&second);
// first and second are still usable here

§Working with Closures

All closures automatically implement the Mutator trait:

use prism3_function::{Mutator, FnMutatorOps};

// Closures can use .mutate() directly
let mut closure = |x: &mut i32| *x *= 2;
let mut value = 5;
closure.mutate(&mut value);
assert_eq!(value, 10);

// Closures can be chained, returning BoxMutator
let mut chained = (|x: &mut i32| *x *= 2)
    .and_then(|x: &mut i32| *x += 10);
let mut value = 5;
chained.mutate(&mut value);
assert_eq!(value, 20);

§Type Conversions

use prism3_function::Mutator;

// Convert closure to concrete type
let closure = |x: &mut i32| *x *= 2;
let mut box_mutator = closure.into_box();

let closure = |x: &mut i32| *x *= 2;
let mut rc_mutator = closure.into_rc();

let closure = |x: &mut i32| *x *= 2;
let mut arc_mutator = closure.into_arc();

§Conditional Execution

All mutator types support conditional execution through the when method, which returns a ConditionalMutator. You can optionally add an or_else branch to create if-then-else logic:

use prism3_function::{Mutator, BoxMutator};

// Simple conditional (if-then)
let mut conditional = BoxMutator::new(|x: &mut i32| *x *= 2)
    .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

// Conditional with else branch (if-then-else)
let mut branched = BoxMutator::new(|x: &mut i32| *x *= 2)
    .when(|x: &i32| *x > 0)
    .or_else(|x: &mut i32| *x -= 1);

let mut positive = 5;
branched.mutate(&mut positive);
assert_eq!(positive, 10); // when branch

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

§Author

Haixing Hu

Structs§

ArcConditionalMutator
ArcConditionalMutator struct
ArcMutator
ArcMutator struct
BoxConditionalMutator
BoxConditionalMutator struct
BoxMutator
BoxMutator struct
RcConditionalMutator
RcConditionalMutator struct
RcMutator
RcMutator struct

Traits§

FnMutatorOps
Extension trait providing mutator composition methods for closures
Mutator
Mutator trait - Unified mutator interface