Skip to main content

qubit_function/mutators/mutator/
fn_mutator_ops.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026.
4 *    Haixing Hu, Qubit Co. Ltd.
5 *
6 *    All rights reserved.
7 *
8 ******************************************************************************/
9//! Defines the `FnMutatorOps` public type.
10
11#![allow(unused_imports)]
12
13use super::*;
14
15// ============================================================================
16// 7. Provide extension methods for closures
17// ============================================================================
18
19/// Extension trait providing mutator composition methods for closures
20///
21/// Provides `and_then` and other composition methods for all closures that
22/// implement `Fn(&mut T)`, enabling direct method chaining on closures
23/// without explicit wrapper types.
24///
25/// # Features
26///
27/// - **Natural Syntax**: Chain operations directly on closures
28/// - **Returns BoxMutator**: Composition results are `BoxMutator<T>` for
29///   continued chaining
30/// - **Zero Cost**: No overhead when composing closures
31/// - **Automatic Implementation**: All `Fn(&mut T)` closures get these
32///   methods automatically
33///
34/// # Examples
35///
36/// ```rust
37/// use qubit_function::{Mutator, FnMutatorOps};
38///
39/// let chained = (|x: &mut i32| *x *= 2)
40///     .and_then(|x: &mut i32| *x += 10);
41/// let mut value = 5;
42/// chained.apply(&mut value);
43/// assert_eq!(value, 20); // (5 * 2) + 10
44/// ```
45///
46/// # Author
47///
48/// Haixing Hu
49pub trait FnMutatorOps<T>: Fn(&mut T) + Sized {
50    /// Chains another mutator in sequence
51    ///
52    /// Returns a new mutator that first executes the current operation, then
53    /// executes the next operation. Consumes the current closure and returns
54    /// `BoxMutator<T>`.
55    ///
56    /// # Parameters
57    ///
58    /// * `next` - The mutator to execute after the current operation. **Note:
59    ///   This parameter is passed by value and will transfer ownership.** If you
60    ///   need to preserve the original mutator, clone it first (if it implements
61    ///   `Clone`). Can be:
62    ///   - A closure: `|x: &mut T|`
63    ///   - A `BoxMutator<T>`
64    ///   - An `ArcMutator<T>`
65    ///   - An `RcMutator<T>`
66    ///   - Any type implementing `Mutator<T>`
67    ///
68    /// # Returns
69    ///
70    /// Returns the composed `BoxMutator<T>`
71    ///
72    /// # Examples
73    ///
74    /// ```rust
75    /// use qubit_function::{Mutator, FnMutatorOps};
76    ///
77    /// let chained = (|x: &mut i32| *x *= 2)
78    ///     .and_then(|x: &mut i32| *x += 10);
79    ///
80    /// let mut value = 5;
81    /// chained.apply(&mut value);
82    /// assert_eq!(value, 20);
83    /// ```
84    fn and_then<C>(self, next: C) -> BoxMutator<T>
85    where
86        Self: 'static,
87        C: Mutator<T> + 'static,
88        T: 'static,
89    {
90        let first = self;
91        let second = next.into_fn();
92        BoxMutator::new(move |t| {
93            (first)(t);
94            (second)(t);
95        })
96    }
97}
98
99/// Implements FnMutatorOps for all closure types
100impl<T, F> FnMutatorOps<T> for F where F: Fn(&mut T) {}