Skip to main content

qubit_function/functions/
bi_mutating_function.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026.
4 *    Haixing Hu, Qubit Co. Ltd.
5 *
6 *    All rights reserved.
7 *
8 ******************************************************************************/
9
10//! # BiMutatingFunction Types
11//!
12//! Provides Rust implementations of bi-mutating-function traits for performing
13//! operations that accept two mutable references and return a result.
14//!
15//! It is similar to the `Fn(&mut T, &mut U) -> R` trait in the standard library.
16//!
17//! This module provides the `BiMutatingFunction<T, U, R>` trait and three
18//! implementations:
19//!
20//! - [`BoxBiMutatingFunction`]: Single ownership, not cloneable
21//! - [`ArcBiMutatingFunction`]: Thread-safe shared ownership, cloneable
22//! - [`RcBiMutatingFunction`]: Single-threaded shared ownership, cloneable
23//!
24//! # Author
25//!
26//! Haixing Hu
27
28use std::rc::Rc;
29use std::sync::Arc;
30
31use crate::functions::{
32    bi_mutating_function_once::BoxBiMutatingFunctionOnce,
33    macros::{
34        impl_box_conditional_function,
35        impl_box_function_methods,
36        impl_conditional_function_clone,
37        impl_conditional_function_debug_display,
38        impl_function_clone,
39        impl_function_common_methods,
40        impl_function_constant_method,
41        impl_function_debug_display,
42        impl_shared_conditional_function,
43        impl_shared_function_methods,
44    },
45    mutating_function::MutatingFunction,
46};
47use crate::macros::{
48    impl_arc_conversions,
49    impl_box_conversions,
50    impl_closure_trait,
51    impl_rc_conversions,
52};
53use crate::predicates::bi_predicate::{
54    ArcBiPredicate,
55    BiPredicate,
56    BoxBiPredicate,
57    RcBiPredicate,
58};
59
60// ============================================================================
61// Core Trait
62// ============================================================================
63
64/// BiMutatingFunction trait - performs operations on two mutable references
65///
66/// Defines the behavior of a bi-mutating-function: computing a value of type `R`
67/// from mutable references to types `T` and `U`, potentially modifying both inputs.
68/// This is analogous to `Fn(&mut T, &mut U) -> R` in Rust's standard library.
69///
70/// # Type Parameters
71///
72/// * `T` - The type of the first input value (mutable reference)
73/// * `U` - The type of the second input value (mutable reference)
74/// * `R` - The type of the output value
75///
76/// # Author
77///
78/// Haixing Hu
79pub trait BiMutatingFunction<T, U, R> {
80    /// Applies the bi-mutating-function to two mutable references and returns a result
81    ///
82    /// # Parameters
83    ///
84    /// * `first` - Mutable reference to the first input value
85    /// * `second` - Mutable reference to the second input value
86    ///
87    /// # Returns
88    ///
89    /// The computed output value
90    fn apply(&self, first: &mut T, second: &mut U) -> R;
91
92    /// Converts to BoxBiMutatingFunction
93    ///
94    /// **⚠️ Consumes `self`**: The original bi-function becomes
95    /// unavailable after calling this method.
96    ///
97    /// # Default Implementation
98    ///
99    /// The default implementation wraps `self` in a `Box` and creates a
100    /// `BoxBiMutatingFunction`. Types can override this method to provide more
101    /// efficient conversions.
102    ///
103    /// # Returns
104    ///
105    /// Returns `BoxBiMutatingFunction<T, U, R>`
106    fn into_box(self) -> BoxBiMutatingFunction<T, U, R>
107    where
108        Self: Sized + 'static,
109    {
110        BoxBiMutatingFunction::new(move |t, u| self.apply(t, u))
111    }
112
113    /// Converts to RcBiMutatingFunction
114    ///
115    /// **⚠️ Consumes `self`**: The original bi-function becomes
116    /// unavailable after calling this method.
117    ///
118    /// # Default Implementation
119    ///
120    /// The default implementation wraps `self` in an `Rc` and creates an
121    /// `RcBiMutatingFunction`. Types can override this method to provide more
122    /// efficient conversions.
123    ///
124    /// # Returns
125    ///
126    /// Returns `RcBiMutatingFunction<T, U, R>`
127    fn into_rc(self) -> RcBiMutatingFunction<T, U, R>
128    where
129        Self: Sized + 'static,
130    {
131        RcBiMutatingFunction::new(move |t, u| self.apply(t, u))
132    }
133
134    /// Converts to ArcBiMutatingFunction
135    ///
136    /// **⚠️ Consumes `self`**: The original bi-function becomes
137    /// unavailable after calling this method.
138    ///
139    /// # Default Implementation
140    ///
141    /// The default implementation wraps `self` in an `Arc` and creates
142    /// an `ArcBiMutatingFunction`. Types can override this method to provide
143    /// more efficient conversions.
144    ///
145    /// # Returns
146    ///
147    /// Returns `ArcBiMutatingFunction<T, U, R>`
148    fn into_arc(self) -> ArcBiMutatingFunction<T, U, R>
149    where
150        Self: Sized + Send + Sync + 'static,
151    {
152        ArcBiMutatingFunction::new(move |t, u| self.apply(t, u))
153    }
154
155    /// Converts bi-mutating-function to a closure
156    ///
157    /// **⚠️ Consumes `self`**: The original bi-function becomes
158    /// unavailable after calling this method.
159    ///
160    /// # Default Implementation
161    ///
162    /// The default implementation creates a closure that captures `self`
163    /// and calls its `apply` method. Types can override this method
164    /// to provide more efficient conversions.
165    ///
166    /// # Returns
167    ///
168    /// Returns a closure that implements `Fn(&mut T, &mut U) -> R`
169    fn into_fn(self) -> impl Fn(&mut T, &mut U) -> R
170    where
171        Self: Sized + 'static,
172    {
173        move |t, u| self.apply(t, u)
174    }
175
176    /// Converts to BiMutatingFunctionOnce
177    ///
178    /// **⚠️ Consumes `self`**: The original bi-function becomes unavailable after calling this method.
179    ///
180    /// Converts a reusable bi-mutating-function to a one-time bi-mutating-function that consumes itself on use.
181    /// This enables passing `BiMutatingFunction` to functions that require `BiMutatingFunctionOnce`.
182    ///
183    /// # Returns
184    ///
185    /// Returns a `BoxBiMutatingFunctionOnce<T, U, R>`
186    fn into_once(self) -> BoxBiMutatingFunctionOnce<T, U, R>
187    where
188        Self: Sized + 'static,
189    {
190        BoxBiMutatingFunctionOnce::new(move |t, u| self.apply(t, u))
191    }
192
193    /// Non-consuming conversion to `BoxBiMutatingFunction` using `&self`.
194    ///
195    /// Default implementation clones `self` and delegates to `into_box`.
196    fn to_box(&self) -> BoxBiMutatingFunction<T, U, R>
197    where
198        Self: Sized + Clone + 'static,
199    {
200        self.clone().into_box()
201    }
202
203    /// Non-consuming conversion to `RcBiMutatingFunction` using `&self`.
204    ///
205    /// Default implementation clones `self` and delegates to `into_rc`.
206    fn to_rc(&self) -> RcBiMutatingFunction<T, U, R>
207    where
208        Self: Sized + Clone + 'static,
209    {
210        self.clone().into_rc()
211    }
212
213    /// Non-consuming conversion to `ArcBiMutatingFunction` using `&self`.
214    ///
215    /// Default implementation clones `self` and delegates to `into_arc`.
216    fn to_arc(&self) -> ArcBiMutatingFunction<T, U, R>
217    where
218        Self: Sized + Clone + Send + Sync + 'static,
219    {
220        self.clone().into_arc()
221    }
222
223    /// Non-consuming conversion to a boxed function using `&self`.
224    ///
225    /// Returns a `Box<dyn Fn(&mut T, &mut U) -> R>` that clones `self` and calls
226    /// `apply` inside the boxed closure.
227    fn to_fn(&self) -> impl Fn(&mut T, &mut U) -> R
228    where
229        Self: Sized + Clone + 'static,
230    {
231        self.clone().into_fn()
232    }
233
234    /// Convert to BiMutatingFunctionOnce without consuming self
235    ///
236    /// **⚠️ Requires Clone**: This method requires `Self` to implement `Clone`.
237    /// Clones the current bi-function and converts the clone to a one-time bi-function.
238    ///
239    /// # Returns
240    ///
241    /// Returns a `BoxBiMutatingFunctionOnce<T, U, R>`
242    fn to_once(&self) -> BoxBiMutatingFunctionOnce<T, U, R>
243    where
244        Self: Clone + 'static,
245    {
246        self.clone().into_once()
247    }
248}
249
250// ============================================================================
251// BoxBiMutatingFunction - Box<dyn Fn(&mut T, &mut U) -> R>
252// ============================================================================
253
254/// BoxBiMutatingFunction - bi-mutating-function wrapper based on `Box<dyn Fn>`
255///
256/// A bi-mutating-function wrapper that provides single ownership with reusable
257/// computation. Borrows both inputs mutably and can be called multiple times.
258///
259/// # Features
260///
261/// - **Based on**: `Box<dyn Fn(&mut T, &mut U) -> R>`
262/// - **Ownership**: Single ownership, cannot be cloned
263/// - **Reusability**: Can be called multiple times (borrows inputs mutably each time)
264/// - **Thread Safety**: Not thread-safe (no `Send + Sync` requirement)
265///
266/// # Author
267///
268/// Haixing Hu
269pub struct BoxBiMutatingFunction<T, U, R> {
270    function: Box<dyn Fn(&mut T, &mut U) -> R>,
271    name: Option<String>,
272}
273
274// Implement BoxBiMutatingFunction
275impl<T, U, R> BoxBiMutatingFunction<T, U, R> {
276    // Generates: new(), new_with_name(), new_with_optional_name(), name(), set_name()
277    impl_function_common_methods!(
278        BoxBiMutatingFunction<T, U, R>,
279        (Fn(&mut T, &mut U) -> R + 'static),
280        |f| Box::new(f)
281    );
282
283    // Generates: when(), and_then()
284    impl_box_function_methods!(
285        BoxBiMutatingFunction<T, U, R>,
286        BoxConditionalBiMutatingFunction,
287        MutatingFunction
288    );
289}
290
291// Implement BiMutatingFunction trait for BoxBiMutatingFunction
292impl<T, U, R> BiMutatingFunction<T, U, R> for BoxBiMutatingFunction<T, U, R> {
293    fn apply(&self, first: &mut T, second: &mut U) -> R {
294        (self.function)(first, second)
295    }
296
297    // Generates: into_box(), into_rc(), into_fn(), into_once()
298    impl_box_conversions!(
299        BoxBiMutatingFunction<T, U, R>,
300        RcBiMutatingFunction,
301        Fn(&mut T, &mut U) -> R,
302        BoxBiMutatingFunctionOnce
303    );
304}
305
306// Implement constant method for BoxBiMutatingFunction
307impl_function_constant_method!(BoxBiMutatingFunction<T, U, R>);
308
309// Implement Debug and Display for BoxBiMutatingFunction
310impl_function_debug_display!(BoxBiMutatingFunction<T, U, R>);
311
312// ============================================================================
313// RcBiMutatingFunction - Rc<dyn Fn(&mut T, &mut U) -> R>
314// ============================================================================
315
316/// RcBiMutatingFunction - single-threaded bi-mutating-function wrapper
317///
318/// A single-threaded, clonable bi-mutating-function wrapper optimized for scenarios
319/// that require sharing without thread-safety overhead.
320///
321/// # Features
322///
323/// - **Based on**: `Rc<dyn Fn(&mut T, &mut U) -> R>`
324/// - **Ownership**: Shared ownership via reference counting (non-atomic)
325/// - **Reusability**: Can be called multiple times (borrows inputs mutably each time)
326/// - **Thread Safety**: Not thread-safe (no `Send + Sync`)
327/// - **Clonable**: Cheap cloning via `Rc::clone`
328///
329/// # Author
330///
331/// Haixing Hu
332pub struct RcBiMutatingFunction<T, U, R> {
333    function: Rc<dyn Fn(&mut T, &mut U) -> R>,
334    name: Option<String>,
335}
336
337impl<T, U, R> RcBiMutatingFunction<T, U, R> {
338    // Generates: new(), new_with_name(), new_with_optional_name(), name(), set_name()
339    impl_function_common_methods!(
340        RcBiMutatingFunction<T, U, R>,
341        (Fn(&mut T, &mut U) -> R + 'static),
342        |f| Rc::new(f)
343    );
344
345    // Generate into_box(), into_rc(), into_fn(), into_once(), to_box(), to_rc(), to_fn(), to_once()
346    impl_shared_function_methods!(
347        RcBiMutatingFunction<T, U, R>,
348        RcConditionalBiMutatingFunction,
349        into_rc,
350        MutatingFunction,
351        'static
352    );
353}
354
355// Implement BiMutatingFunction trait for RcBiMutatingFunction
356impl<T, U, R> BiMutatingFunction<T, U, R> for RcBiMutatingFunction<T, U, R> {
357    fn apply(&self, first: &mut T, second: &mut U) -> R {
358        (self.function)(first, second)
359    }
360
361    // Generate into_box(), into_rc(), into_fn(), into_once(), to_box(), to_rc(), to_fn(), to_once()
362    impl_rc_conversions!(
363        RcBiMutatingFunction<T, U, R>,
364        BoxBiMutatingFunction,
365        BoxBiMutatingFunctionOnce,
366        Fn(first: &mut T, second: &mut U) -> R
367    );
368}
369
370// Implement constant method for RcBiMutatingFunction
371impl_function_constant_method!(RcBiMutatingFunction<T, U, R>);
372
373// Implement Debug and Display for RcBiMutatingFunction
374impl_function_debug_display!(RcBiMutatingFunction<T, U, R>);
375
376// Implement Clone for RcBiMutatingFunction
377impl_function_clone!(RcBiMutatingFunction<T, U, R>);
378
379// ============================================================================
380// ArcBiMutatingFunction - Arc<dyn Fn(&mut T, &mut U) -> R + Send + Sync>
381// ============================================================================
382
383/// ArcBiMutatingFunction - thread-safe bi-mutating-function wrapper
384///
385/// A thread-safe, clonable bi-mutating-function wrapper suitable for multi-threaded
386/// scenarios. Can be called multiple times and shared across threads.
387///
388/// # Features
389///
390/// - **Based on**: `Arc<dyn Fn(&mut T, &mut U) -> R + Send + Sync>`
391/// - **Ownership**: Shared ownership via reference counting
392/// - **Reusability**: Can be called multiple times (borrows inputs mutably each time)
393/// - **Thread Safety**: Thread-safe (`Send + Sync` required)
394/// - **Clonable**: Cheap cloning via `Arc::clone`
395///
396/// # Author
397///
398/// Haixing Hu
399pub struct ArcBiMutatingFunction<T, U, R> {
400    function: Arc<dyn Fn(&mut T, &mut U) -> R + Send + Sync>,
401    name: Option<String>,
402}
403
404impl<T, U, R> ArcBiMutatingFunction<T, U, R> {
405    // Generates: new(), new_with_name(), new_with_optional_name(), name(), set_name()
406    impl_function_common_methods!(
407        ArcBiMutatingFunction<T, U, R>,
408        (Fn(&mut T, &mut U) -> R + Send + Sync + 'static),
409        |f| Arc::new(f)
410    );
411
412    // Generate into_box(), into_rc(), into_fn(), into_once(), to_box(), to_rc(), to_fn(), to_once()
413    impl_shared_function_methods!(
414        ArcBiMutatingFunction<T, U, R>,
415        ArcConditionalBiMutatingFunction,
416        into_arc,
417        MutatingFunction,
418        Send + Sync + 'static
419    );
420}
421
422// Implement BiMutatingFunction trait for ArcBiMutatingFunction
423impl<T, U, R> BiMutatingFunction<T, U, R> for ArcBiMutatingFunction<T, U, R> {
424    fn apply(&self, first: &mut T, second: &mut U) -> R {
425        (self.function)(first, second)
426    }
427
428    // Generate into_box(), into_rc(), into_fn(), into_once(), to_box(), to_rc(), to_fn(), to_once()
429    impl_arc_conversions!(
430        ArcBiMutatingFunction<T, U, R>,
431        BoxBiMutatingFunction,
432        RcBiMutatingFunction,
433        BoxBiMutatingFunctionOnce,
434        Fn(first: &mut T, second: &mut U) -> R
435    );
436}
437
438// Implement constant method for ArcBiMutatingFunction
439impl_function_constant_method!(ArcBiMutatingFunction<T, U, R>, Send + Sync + 'static);
440
441// Implement Debug and Display for ArcBiMutatingFunction
442impl_function_debug_display!(ArcBiMutatingFunction<T, U, R>);
443
444// Implement Clone for ArcBiMutatingFunction
445impl_function_clone!(ArcBiMutatingFunction<T, U, R>);
446
447// ============================================================================
448// Blanket implementation for standard Fn trait
449// ============================================================================
450
451// Implement BiMutatingFunction<T, U, R> for any type that implements Fn(&mut T, &mut U) -> R
452impl_closure_trait!(
453    BiMutatingFunction<T, U, R>,
454    apply,
455    BoxBiMutatingFunctionOnce,
456    Fn(first: &mut T, second: &mut U) -> R
457);
458
459// ============================================================================
460// FnBiMutatingFunctionOps - Extension trait for Fn(&mut T, &mut U) -> R bi-functions
461// ============================================================================
462
463/// Extension trait for closures implementing `Fn(&mut T, &mut U) -> R`
464///
465/// Provides composition methods (`and_then`, `when`) for bi-mutating-function
466/// closures and function pointers without requiring explicit wrapping in
467/// `BoxBiMutatingFunction`.
468///
469/// This trait is automatically implemented for all closures and function
470/// pointers that implement `Fn(&mut T, &mut U) -> R`.
471///
472/// # Design Rationale
473///
474/// While closures automatically implement `BiMutatingFunction<T, U, R>` through
475/// blanket implementation, they don't have access to instance methods like
476/// `and_then` and `when`. This extension trait provides those methods,
477/// returning `BoxBiMutatingFunction` for maximum flexibility.
478///
479/// # Examples
480///
481/// ## Chain composition with and_then
482///
483/// ```rust
484/// use qubit_function::{BiMutatingFunction, FnBiMutatingFunctionOps};
485///
486/// let swap_and_sum = |x: &mut i32, y: &mut i32| {
487///     let temp = *x;
488///     *x = *y;
489///     *y = temp;
490///     *x + *y
491/// };
492/// let double = |x: &i32| x * 2;
493///
494/// let composed = swap_and_sum.and_then(double);
495/// let mut a = 3;
496/// let mut b = 5;
497/// assert_eq!(composed.apply(&mut a, &mut b), 16); // (5 + 3) * 2 = 16
498/// ```
499///
500/// ## Conditional execution with when
501///
502/// ```rust
503/// use qubit_function::{BiMutatingFunction, FnBiMutatingFunctionOps};
504///
505/// let swap_and_sum = |x: &mut i32, y: &mut i32| {
506///     let temp = *x;
507///     *x = *y;
508///     *y = temp;
509///     *x + *y
510/// };
511/// let multiply = |x: &mut i32, y: &mut i32| {
512///     *x *= *y;
513///     *x
514/// };
515///
516/// let conditional = swap_and_sum.when(|x: &i32, y: &i32| *x > 0 && *y > 0).or_else(multiply);
517///
518/// let mut a = 5;
519/// let mut b = 3;
520/// assert_eq!(conditional.apply(&mut a, &mut b), 8);   // swap_and_sum: (3 + 5)
521///
522/// let mut a = -5;
523/// let mut b = 3;
524/// assert_eq!(conditional.apply(&mut a, &mut b), -15); // multiply: (-5 * 3)
525/// ```
526///
527/// # Author
528///
529/// Haixing Hu
530pub trait FnBiMutatingFunctionOps<T, U, R>: Fn(&mut T, &mut U) -> R + Sized {
531    /// Chain composition - applies self first, then after
532    ///
533    /// Creates a new bi-mutating-function that applies this bi-mutating-function first,
534    /// then applies the after function to the result. Consumes self and
535    /// returns a `BoxBiMutatingFunction`.
536    ///
537    /// # Type Parameters
538    ///
539    /// * `S` - The output type of the after function
540    /// * `F` - The type of the after function (must implement Function<R, S>)
541    ///
542    /// # Parameters
543    ///
544    /// * `after` - The function to apply after self. **Note: This parameter
545    ///   is passed by value and will transfer ownership.** If you need to
546    ///   preserve the original function, clone it first (if it implements
547    ///   `Clone`). Can be:
548    ///   - A closure: `|x: R| -> S`
549    ///   - A function pointer: `fn(R) -> S`
550    ///   - A `BoxFunction<R, S>`
551    ///   - An `RcFunction<R, S>`
552    ///   - An `ArcFunction<R, S>`
553    ///   - Any type implementing `Function<R, S>`
554    ///
555    /// # Returns
556    ///
557    /// A new `BoxBiMutatingFunction<T, U, S>` representing the composition
558    ///
559    /// # Examples
560    ///
561    /// ## Direct value passing (ownership transfer)
562    ///
563    /// ```rust
564    /// use qubit_function::{BiMutatingFunction, FnBiMutatingFunctionOps,
565    ///     BoxFunction, Function};
566    ///
567    /// let swap = |x: &mut i32, y: &mut i32| {
568    ///     let temp = *x;
569    ///     *x = *y;
570    ///     *y = temp;
571    ///     *x + *y
572    /// };
573    /// let to_string = BoxFunction::new(|x: &i32| x.to_string());
574    ///
575    /// // to_string is moved here
576    /// let composed = swap.and_then(to_string);
577    /// let mut a = 20;
578    /// let mut b = 22;
579    /// assert_eq!(composed.apply(&mut a, &mut b), "42");
580    /// // to_string.apply(10); // Would not compile - moved
581    /// ```
582    ///
583    /// ## Preserving original with clone
584    ///
585    /// ```rust
586    /// use qubit_function::{BiMutatingFunction, FnBiMutatingFunctionOps,
587    ///     Function, RcFunction};
588    ///
589    /// let swap = |x: &mut i32, y: &mut i32| {
590    ///     let temp = *x;
591    ///     *x = *y;
592    ///     *y = temp;
593    ///     *x + *y
594    /// };
595    /// let to_string = RcFunction::new(|x: &i32| x.to_string());
596    ///
597    /// // Clone to preserve original
598    /// let composed = swap.and_then(to_string.clone());
599    /// let mut a = 20;
600    /// let mut b = 22;
601    /// assert_eq!(composed.apply(&mut a, &mut b), "42");
602    ///
603    /// // Original still usable
604    /// assert_eq!(to_string.apply(&10), "10");
605    /// ```
606    fn and_then<S, F>(self, after: F) -> BoxBiMutatingFunction<T, U, S>
607    where
608        Self: 'static,
609        S: 'static,
610        F: crate::functions::function::Function<R, S> + 'static,
611        T: 'static,
612        U: 'static,
613        R: 'static,
614    {
615        BoxBiMutatingFunction::new(move |t: &mut T, u: &mut U| after.apply(&self(t, u)))
616    }
617
618    /// Creates a conditional bi-mutating-function
619    ///
620    /// Returns a bi-mutating-function that only executes when a bi-predicate is
621    /// satisfied. You must call `or_else()` to provide an alternative
622    /// bi-mutating-function for when the condition is not satisfied.
623    ///
624    /// # Parameters
625    ///
626    /// * `predicate` - The condition to check. **Note: This parameter is passed
627    ///   by value and will transfer ownership.** If you need to preserve the
628    ///   original bi-predicate, clone it first (if it implements `Clone`).
629    ///   Can be:
630    ///   - A closure: `|x: &mut T, y: &mut U| -> bool`
631    ///   - A function pointer: `fn(&mut T, &mut U) -> bool`
632    ///   - A `BoxBiPredicate<T, U>`
633    ///   - An `RcBiPredicate<T, U>`
634    ///   - An `ArcBiPredicate<T, U>`
635    ///   - Any type implementing `BiPredicate<T, U>`
636    ///
637    /// # Returns
638    ///
639    /// Returns `BoxConditionalBiMutatingFunction<T, U, R>`
640    ///
641    /// # Examples
642    ///
643    /// ## Basic usage with or_else
644    ///
645    /// ```rust
646    /// use qubit_function::{BiMutatingFunction, FnBiMutatingFunctionOps};
647    ///
648    /// let swap_and_sum = |x: &mut i32, y: &mut i32| {
649    ///     let temp = *x;
650    ///     *x = *y;
651    ///     *y = temp;
652    ///     *x + *y
653    /// };
654    /// let multiply = |x: &mut i32, y: &mut i32| {
655    ///     *x *= *y;
656    ///     *x
657    /// };
658    /// let conditional = swap_and_sum.when(|x: &i32, y: &i32| *x > 0)
659    ///     .or_else(multiply);
660    ///
661    /// let mut a = 5;
662    /// let mut b = 3;
663    /// assert_eq!(conditional.apply(&mut a, &mut b), 8);
664    /// ```
665    ///
666    /// ## Preserving bi-predicate with clone
667    ///
668    /// ```rust
669    /// use qubit_function::{BiMutatingFunction, FnBiMutatingFunctionOps,
670    ///     RcBiPredicate};
671    ///
672    /// let swap_and_sum = |x: &mut i32, y: &mut i32| {
673    ///     let temp = *x;
674    ///     *x = *y;
675    ///     *y = temp;
676    ///     *x + *y
677    /// };
678    /// let both_positive = RcBiPredicate::new(|x: &i32, y: &i32|
679    ///     *x > 0 && *y > 0);
680    ///
681    /// // Clone to preserve original bi-predicate
682    /// let conditional = swap_and_sum.when(both_positive.clone())
683    ///     .or_else(|x: &mut i32, y: &mut i32| *x * *y);
684    ///
685    /// let mut a = 5;
686    /// let mut b = 3;
687    /// assert_eq!(conditional.apply(&mut a, &mut b), 8);
688    ///
689    /// // Original bi-predicate still usable
690    /// use qubit_function::BiPredicate;
691    /// let test_a = 5;
692    /// let test_b = 3;
693    /// assert!(both_positive.test(&test_a, &test_b));
694    /// ```
695    fn when<P>(self, predicate: P) -> BoxConditionalBiMutatingFunction<T, U, R>
696    where
697        Self: 'static,
698        P: BiPredicate<T, U> + 'static,
699        T: 'static,
700        U: 'static,
701        R: 'static,
702    {
703        BoxBiMutatingFunction::new(self).when(predicate)
704    }
705}
706
707/// Blanket implementation of FnBiMutatingFunctionOps for all closures
708///
709/// Automatically implements `FnBiMutatingFunctionOps<T, U, R>` for any type that
710/// implements `Fn(&mut T, &mut U) -> R`.
711///
712/// # Author
713///
714/// Haixing Hu
715impl<T, U, R, F> FnBiMutatingFunctionOps<T, U, R> for F where F: Fn(&mut T, &mut U) -> R {}
716
717// ============================================================================
718// Type Aliases for BinaryMutatingOperator (BiMutatingFunction<T, U, R> where T == U)
719// ============================================================================
720
721/// Type alias for `BoxBiMutatingFunction<T, T, R>`
722///
723/// Represents a binary mutating function that takes two values of type `T` and produces
724/// a value of type `R`, with single ownership semantics. Similar to Java's
725/// `BiFunction<T, T, R>` but with mutable references.
726///
727/// # Examples
728///
729/// ```rust
730/// use qubit_function::{BoxBinaryMutatingFunction, BiMutatingFunction};
731///
732/// let swap_and_sum: BoxBinaryMutatingFunction<i32, i32> = BoxBinaryMutatingFunction::new(|x, y| {
733///     let temp = *x;
734///     *x = *y;
735///     *y = temp;
736///     *x + *y
737/// });
738/// let mut a = 5;
739/// let mut b = 10;
740/// assert_eq!(swap_and_sum.apply(&mut a, &mut b), 15);
741/// assert_eq!(a, 10);
742/// assert_eq!(b, 5);
743/// ```
744///
745/// # Author
746///
747/// Haixing Hu
748pub type BoxBinaryMutatingFunction<T, R> = BoxBiMutatingFunction<T, T, R>;
749
750/// Type alias for `ArcBiMutatingFunction<T, T, R>`
751///
752/// Represents a thread-safe binary mutating function that takes two values of type `T`
753/// and produces a value of type `R`. Similar to Java's `BiFunction<T, T, R>`
754/// with shared, thread-safe ownership and mutable references.
755///
756/// # Examples
757///
758/// ```rust
759/// use qubit_function::{ArcBinaryMutatingFunction, BiMutatingFunction};
760///
761/// let swap_and_sum: ArcBinaryMutatingFunction<i32, i32> = ArcBinaryMutatingFunction::new(|x, y| {
762///     let temp = *x;
763///     *x = *y;
764///     *y = temp;
765///     *x + *y
766/// });
767/// let swap_clone = swap_and_sum.clone();
768/// let mut a = 5;
769/// let mut b = 10;
770/// assert_eq!(swap_and_sum.apply(&mut a, &mut b), 15);
771/// assert_eq!(swap_clone.apply(&mut a, &mut b), 15);
772/// ```
773///
774/// # Author
775///
776/// Haixing Hu
777pub type ArcBinaryMutatingFunction<T, R> = ArcBiMutatingFunction<T, T, R>;
778
779/// Type alias for `RcBiMutatingFunction<T, T, R>`
780///
781/// Represents a single-threaded binary mutating function that takes two values of type `T`
782/// and produces a value of type `R`. Similar to Java's `BiFunction<T, T, R>`
783/// with shared, single-threaded ownership and mutable references.
784///
785/// # Examples
786///
787/// ```rust
788/// use qubit_function::{RcBinaryMutatingFunction, BiMutatingFunction};
789///
790/// let swap_and_sum: RcBinaryMutatingFunction<i32, i32> = RcBinaryMutatingFunction::new(|x, y| {
791///     let temp = *x;
792///     *x = *y;
793///     *y = temp;
794///     *x + *y
795/// });
796/// let swap_clone = swap_and_sum.clone();
797/// let mut a = 5;
798/// let mut b = 10;
799/// assert_eq!(swap_and_sum.apply(&mut a, &mut b), 15);
800/// assert_eq!(swap_clone.apply(&mut a, &mut b), 15);
801/// ```
802///
803/// # Author
804///
805/// Haixing Hu
806pub type RcBinaryMutatingFunction<T, R> = RcBiMutatingFunction<T, T, R>;
807
808// ============================================================================
809// BoxConditionalBiMutatingFunction - Box-based Conditional BiMutatingFunction
810// ============================================================================
811
812/// BoxConditionalBiMutatingFunction struct
813///
814/// A conditional bi-mutating-function that only executes when a bi-predicate is
815/// satisfied. Uses `BoxBiMutatingFunction` and `BoxBiPredicate` for single
816/// ownership semantics.
817///
818/// This type is typically created by calling `BoxBiMutatingFunction::when()` and is
819/// designed to work with the `or_else()` method to create if-then-else logic.
820///
821/// # Features
822///
823/// - **Single Ownership**: Not cloneable, ownership moves on use
824/// - **Conditional Execution**: Only computes when bi-predicate returns `true`
825/// - **Chainable**: Can add `or_else` branch to create if-then-else logic
826/// - **Implements BiMutatingFunction**: Can be used anywhere a `BiMutatingFunction` is expected
827///
828/// # Author
829///
830/// Haixing Hu
831pub struct BoxConditionalBiMutatingFunction<T, U, R> {
832    function: BoxBiMutatingFunction<T, U, R>,
833    predicate: BoxBiPredicate<T, U>,
834}
835
836// Implement BoxConditionalBiMutatingFunction
837impl_box_conditional_function!(
838    BoxConditionalBiMutatingFunction<T, U, R>,
839    BoxBiMutatingFunction,
840    BiMutatingFunction
841);
842
843// Use macro to generate Debug and Display implementations
844impl_conditional_function_debug_display!(BoxConditionalBiMutatingFunction<T, U, R>);
845
846// ============================================================================
847// RcConditionalBiMutatingFunction - Rc-based Conditional BiMutatingFunction
848// ============================================================================
849
850/// RcConditionalBiMutatingFunction struct
851///
852/// A single-threaded conditional bi-mutating-function that only executes when a
853/// bi-predicate is satisfied. Uses `RcBiMutatingFunction` and `RcBiPredicate` for
854/// shared ownership within a single thread.
855///
856/// This type is typically created by calling `RcBiMutatingFunction::when()` and is
857/// designed to work with the `or_else()` method to create if-then-else logic.
858///
859/// # Features
860///
861/// - **Shared Ownership**: Cloneable via `Rc`, multiple owners allowed
862/// - **Single-Threaded**: Not thread-safe, cannot be sent across threads
863/// - **Conditional Execution**: Only computes when bi-predicate returns `true`
864/// - **No Lock Overhead**: More efficient than `ArcConditionalBiMutatingFunction`
865///
866/// # Author
867///
868/// Haixing Hu
869pub struct RcConditionalBiMutatingFunction<T, U, R> {
870    function: RcBiMutatingFunction<T, U, R>,
871    predicate: RcBiPredicate<T, U>,
872}
873
874// Implement RcConditionalBiMutatingFunction
875impl_shared_conditional_function!(
876    RcConditionalBiMutatingFunction<T, U, R>,
877    RcBiMutatingFunction,
878    BiMutatingFunction,
879    into_rc,
880    'static
881);
882
883// Use macro to generate Debug and Display implementations
884impl_conditional_function_debug_display!(RcConditionalBiMutatingFunction<T, U, R>);
885
886// Generate Clone implementation
887impl_conditional_function_clone!(RcConditionalBiMutatingFunction<T, U, R>);
888
889// ============================================================================
890// ArcConditionalBiMutatingFunction - Arc-based Conditional BiMutatingFunction
891// ============================================================================
892
893/// ArcConditionalBiMutatingFunction struct
894///
895/// A thread-safe conditional bi-mutating-function that only executes when a
896/// bi-predicate is satisfied. Uses `ArcBiMutatingFunction` and `ArcBiPredicate` for
897/// shared ownership across threads.
898///
899/// This type is typically created by calling `ArcBiMutatingFunction::when()` and is
900/// designed to work with the `or_else()` method to create if-then-else logic.
901///
902/// # Features
903///
904/// - **Shared Ownership**: Cloneable via `Arc`, multiple owners allowed
905/// - **Thread-Safe**: Implements `Send + Sync`, safe for concurrent use
906/// - **Conditional Execution**: Only computes when bi-predicate returns `true`
907/// - **Chainable**: Can add `or_else` branch to create if-then-else logic
908///
909/// # Author
910///
911/// Haixing Hu
912pub struct ArcConditionalBiMutatingFunction<T, U, R> {
913    function: ArcBiMutatingFunction<T, U, R>,
914    predicate: ArcBiPredicate<T, U>,
915}
916
917// Implement ArcConditionalBiMutatingFunction
918impl_shared_conditional_function!(
919    ArcConditionalBiMutatingFunction<T, U, R>,
920    ArcBiMutatingFunction,
921    BiMutatingFunction,
922    into_arc,
923    Send + Sync + 'static
924);
925
926// Use macro to generate Debug and Display implementations
927impl_conditional_function_debug_display!(ArcConditionalBiMutatingFunction<T, U, R>);
928
929// Generate Clone implementation
930impl_conditional_function_clone!(ArcConditionalBiMutatingFunction<T, U, R>);