Module mutator_once

Module mutator_once 

Source
Expand description

§MutatorOnce Types

Provides Java-style one-time Mutator interface implementations for performing operations that consume self and modify the input value.

This module provides a unified MutatorOnce trait and a Box-based single ownership implementation:

  • BoxMutatorOnce<T>: Box-based single ownership implementation for one-time use scenarios

§Design Philosophy

The key difference between MutatorOnce and Mutator:

  • Mutator: &mut self, can be called multiple times, uses FnMut(&mut T)
  • MutatorOnce: self, can only be called once, uses FnOnce(&mut T)

§MutatorOnce vs Mutator

FeatureMutatorMutatorOnce
Self Parameter&mut selfself
Call CountMultipleOnce
Closure TypeFnMut(&mut T)FnOnce(&mut T)
Use CasesRepeatable modificationsOne-time resource transfers, init callbacks

§Why MutatorOnce?

Core value of MutatorOnce:

  1. Store FnOnce closures: Allows moving captured variables
  2. Delayed execution: Store in data structures, execute later
  3. Resource transfer: Suitable for scenarios requiring ownership transfer

§Why Only Box Variant?

  • Arc/Rc conflicts with FnOnce semantics: FnOnce can only be called once, while shared ownership implies multiple references
  • Box is perfect match: Single ownership aligns perfectly with one-time call semantics

§Use Cases

§BoxMutatorOnce

  • Post-initialization callbacks (moving data)
  • Resource transfer (moving Vec, String, etc.)
  • One-time complex operations (requiring moved capture variables)

§Examples

§Basic Usage

use prism3_function::{BoxMutatorOnce, MutatorOnce};

let data = vec![1, 2, 3];
let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
    x.extend(data); // Move data
});

let mut target = vec![0];
mutator.mutate_once(&mut target);
assert_eq!(target, vec![0, 1, 2, 3]);

§Method Chaining

use prism3_function::{BoxMutatorOnce, MutatorOnce};

let data1 = vec![1, 2];
let data2 = vec![3, 4];

let chained = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
    x.extend(data1);
})
.and_then(move |x: &mut Vec<i32>| {
    x.extend(data2);
});

let mut target = vec![0];
chained.mutate_once(&mut target);
assert_eq!(target, vec![0, 1, 2, 3, 4]);

§Initialization Callback

use prism3_function::{BoxMutatorOnce, MutatorOnce};

struct Initializer {
    on_complete: Option<BoxMutatorOnce<Vec<i32>>>,
}

impl Initializer {
    fn new<F>(callback: F) -> Self
    where
        F: FnOnce(&mut Vec<i32>) + 'static
    {
        Self {
            on_complete: Some(BoxMutatorOnce::new(callback))
        }
    }

    fn run(mut self, data: &mut Vec<i32>) {
        // Execute initialization logic
        data.push(42);

        // Call callback
        if let Some(callback) = self.on_complete.take() {
            callback.mutate_once(data);
        }
    }
}

let data_to_add = vec![1, 2, 3];
let init = Initializer::new(move |x| {
    x.extend(data_to_add); // Move data_to_add
});

let mut result = Vec::new();
init.run(&mut result);
assert_eq!(result, vec![42, 1, 2, 3]);

§Author

Haixing Hu

Structs§

BoxConditionalMutatorOnce
BoxConditionalMutatorOnce struct
BoxMutatorOnce
BoxMutatorOnce struct

Traits§

FnMutatorOnceOps
Extension trait providing one-time mutator composition methods for closures
MutatorOnce
MutatorOnce trait - One-time mutator interface