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 patternsArcMutator<T>: Arc<Mutex<>>-based thread-safe shared ownership implementation for multi-threaded scenariosRcMutator<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
| Type | Input | Modifies Input? | Modifies Self? | Use Cases |
|---|---|---|---|---|
| Consumer | &T | ❌ | ✅ | Observe, log, count, notify |
| Mutator | &mut T | ✅ | ✅ | Modify, 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
| Feature | BoxMutator | ArcMutator | RcMutator |
|---|---|---|---|
| Ownership | Single | Shared | Shared |
| Cloneable | ❌ | ✅ | ✅ |
| Thread-Safe | ❌ | ✅ | ❌ |
| Interior Mut. | N/A | Mutex | RefCell |
and_then API | self | &self | &self |
| Lock Overhead | None | Yes | None |
§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§
- ArcConditional
Mutator - ArcConditionalMutator struct
- ArcMutator
- ArcMutator struct
- BoxConditional
Mutator - BoxConditionalMutator struct
- BoxMutator
- BoxMutator struct
- RcConditional
Mutator - RcConditionalMutator struct
- RcMutator
- RcMutator struct
Traits§
- FnMutator
Ops - Extension trait providing mutator composition methods for closures
- Mutator
- Mutator trait - Unified mutator interface