qubit_function/functions/mutating_function.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2025 - 2026 Haixing Hu.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10//! # MutatingFunction Types
11//!
12//! Provides Java-like `MutatingFunction` interface implementations for
13//! performing operations that accept a mutable reference and return a result.
14//!
15//! It is similar to the `Fn(&mut T) -> R` trait in the standard library.
16//!
17//! This module provides a unified `MutatingFunction` trait and three concrete
18//! implementations based on different ownership models:
19//!
20//! - **`BoxMutatingFunction<T, R>`**: Box-based single ownership
21//! implementation
22//! - **`ArcMutatingFunction<T, R>`**: Arc-based thread-safe shared ownership
23//! implementation
24//! - **`RcMutatingFunction<T, R>`**: Rc-based single-threaded shared
25//! ownership implementation
26//!
27//! # Design Philosophy
28//!
29//! `MutatingFunction` bridges the gap between `Function` and `Mutator`:
30//!
31//! - **Function**: `Fn(&T) -> R` - reads input, returns result
32//! - **Mutator**: `Fn(&mut T)` - modifies input, no return
33//! - **MutatingFunction**: `Fn(&mut T) -> R` - modifies input AND returns
34//! result
35//!
36//! ## Comparison with Related Types
37//!
38//! | Type | Input | Modifies? | Returns? | Use Cases |
39//! |------|-------|-----------|----------|-----------|
40//! | **Function** | `&T` | ❌ | ✅ | Read-only transform |
41//! | **Mutator** | `&mut T` | ✅ | ❌ | In-place modification |
42//! | **MutatingFunction** | `&mut T` | ✅ | ✅ | Modify + return info |
43//! | **Transformer** | `T` | N/A | ✅ | Consume + transform |
44//!
45//! **Key Insight**: Use `MutatingFunction` when you need to both modify the
46//! input and return information about the modification or the previous state.
47//!
48//! # Comparison Table
49//!
50//! | Feature | Box | Arc | Rc |
51//! |------------------|-----|-----|----|
52//! | Ownership | Single | Shared | Shared |
53//! | Cloneable | ❌ | ✅ | ✅ |
54//! | Thread-Safe | ❌ | ✅ | ❌ |
55//! | Interior Mut. | N/A | N/A | N/A |
56//! | `and_then` API | `self` | `&self` | `&self` |
57//! | Lock Overhead | None | None | None |
58//!
59//! # Use Cases
60//!
61//! ## Common Scenarios
62//!
63//! - **Atomic operations**: Increment counter and return new value
64//! - **Cache updates**: Update cache and return old value
65//! - **Validation**: Validate and fix data, return validation result
66//! - **Event handlers**: Process event and return whether to continue
67//! - **State machines**: Transition state and return transition info
68//!
69//! # Examples
70//!
71//! ## Basic Usage
72//!
73//! ```rust
74//! use qubit_function::{BoxMutatingFunction, MutatingFunction};
75//!
76//! // Increment counter and return new value
77//! let incrementer = BoxMutatingFunction::new(|x: &mut i32| {
78//! *x += 1;
79//! *x
80//! });
81//!
82//! let mut value = 5;
83//! let result = incrementer.apply(&mut value);
84//! assert_eq!(value, 6);
85//! assert_eq!(result, 6);
86//! ```
87//!
88//! ## Method Chaining
89//!
90//! ```rust
91//! use qubit_function::{BoxMutatingFunction, MutatingFunction};
92//!
93//! let chained = BoxMutatingFunction::new(|x: &mut i32| {
94//! *x *= 2;
95//! *x
96//! })
97//! .and_then(|x: &i32| x + 10);
98//!
99//! let mut value = 5;
100//! let result = chained.apply(&mut value);
101//! assert_eq!(value, 10); // (5 * 2), value is still mutated by the first function
102//! assert_eq!(result, 20);
103//! ```
104//!
105//! ## Cache Update Pattern
106//!
107//! ```rust
108//! use qubit_function::{BoxMutatingFunction, MutatingFunction};
109//! use std::collections::HashMap;
110//!
111//! let updater = BoxMutatingFunction::new(
112//! |cache: &mut HashMap<String, i32>| {
113//! cache.insert("key".to_string(), 42)
114//! }
115//! );
116//!
117//! let mut cache = HashMap::new();
118//! cache.insert("key".to_string(), 10);
119//! let old_value = updater.apply(&mut cache);
120//! assert_eq!(old_value, Some(10));
121//! assert_eq!(cache.get("key"), Some(&42));
122//! ```
123//!
124use std::rc::Rc;
125use std::sync::Arc;
126
127use crate::functions::{
128 function::Function,
129 macros::{
130 impl_box_conditional_function,
131 impl_box_function_methods,
132 impl_conditional_function_clone,
133 impl_conditional_function_debug_display,
134 impl_fn_ops_trait,
135 impl_function_clone,
136 impl_function_common_methods,
137 impl_function_debug_display,
138 impl_function_identity_method,
139 impl_shared_conditional_function,
140 impl_shared_function_methods,
141 },
142 mutating_function_once::BoxMutatingFunctionOnce,
143};
144use crate::macros::{
145 impl_arc_conversions,
146 impl_box_conversions,
147 impl_closure_trait,
148 impl_rc_conversions,
149};
150use crate::predicates::predicate::{
151 ArcPredicate,
152 BoxPredicate,
153 Predicate,
154 RcPredicate,
155};
156
157mod box_mutating_function;
158pub use box_mutating_function::BoxMutatingFunction;
159mod rc_mutating_function;
160pub use rc_mutating_function::RcMutatingFunction;
161mod arc_mutating_function;
162pub use arc_mutating_function::ArcMutatingFunction;
163mod box_conditional_mutating_function;
164pub use box_conditional_mutating_function::BoxConditionalMutatingFunction;
165mod rc_conditional_mutating_function;
166pub use rc_conditional_mutating_function::RcConditionalMutatingFunction;
167mod arc_conditional_mutating_function;
168pub use arc_conditional_mutating_function::ArcConditionalMutatingFunction;
169mod fn_mutating_function_ops;
170pub use fn_mutating_function_ops::FnMutatingFunctionOps;
171
172// =======================================================================
173// 1. MutatingFunction Trait - Unified Interface
174// =======================================================================
175
176/// MutatingFunction trait - Unified mutating function interface
177///
178/// It is similar to the `Fn(&mut T) -> R` trait in the standard library.
179///
180/// Defines the core behavior of all mutating function types. Performs
181/// operations that accept a mutable reference, potentially modify it, and
182/// return a result.
183///
184/// This trait is automatically implemented by:
185/// - All closures implementing `Fn(&mut T) -> R`
186/// - `BoxMutatingFunction<T, R>`, `ArcMutatingFunction<T, R>`, and
187/// `RcMutatingFunction<T, R>`
188///
189/// # Design Rationale
190///
191/// The trait provides a unified abstraction over different ownership models
192/// for operations that both modify input and return results. This is useful
193/// for scenarios where you need to:
194/// - Update state and return information about the update
195/// - Perform atomic-like operations (modify and return)
196/// - Implement event handlers that modify state and signal continuation
197///
198/// # Features
199///
200/// - **Unified Interface**: All mutating function types share the same
201/// `apply` method signature
202/// - **Automatic Implementation**: Closures automatically implement this
203/// trait
204/// - **Type Conversions**: Easy conversion between ownership models
205/// - **Generic Programming**: Write functions that work with any mutating
206/// function type
207///
208/// # Examples
209///
210/// ## Generic Function
211///
212/// ```rust
213/// use qubit_function::{MutatingFunction, BoxMutatingFunction};
214///
215/// fn apply_and_log<F: MutatingFunction<i32, i32>>(
216/// func: &F,
217/// value: i32
218/// ) -> i32 {
219/// let mut val = value;
220/// let result = func.apply(&mut val);
221/// println!("Modified: {} -> {}, returned: {}", value, val, result);
222/// result
223/// }
224///
225/// let incrementer = BoxMutatingFunction::new(|x: &mut i32| {
226/// *x += 1;
227/// *x
228/// });
229/// assert_eq!(apply_and_log(&incrementer, 5), 6);
230/// ```
231///
232/// ## Type Conversion
233///
234/// ```rust
235/// use qubit_function::MutatingFunction;
236///
237/// let closure = |x: &mut i32| {
238/// *x *= 2;
239/// *x
240/// };
241///
242/// // Convert to different ownership models
243/// let box_func = closure.into_box();
244/// // let rc_func = closure.into_rc(); // closure moved
245/// // let arc_func = closure.into_arc(); // closure moved
246/// ```
247///
248pub trait MutatingFunction<T, R> {
249 /// Applies the function to the mutable reference and returns a result
250 ///
251 /// Executes an operation on the given mutable reference, potentially
252 /// modifying it, and returns a result value.
253 ///
254 /// # Parameters
255 ///
256 /// * `t` - A mutable reference to the input value
257 ///
258 /// # Returns
259 ///
260 /// The computed result value
261 ///
262 /// # Examples
263 ///
264 /// ```rust
265 /// use qubit_function::{MutatingFunction, BoxMutatingFunction};
266 ///
267 /// let func = BoxMutatingFunction::new(|x: &mut i32| {
268 /// let old = *x;
269 /// *x += 1;
270 /// old
271 /// });
272 ///
273 /// let mut value = 5;
274 /// let old_value = func.apply(&mut value);
275 /// assert_eq!(old_value, 5);
276 /// assert_eq!(value, 6);
277 /// ```
278 fn apply(&self, t: &mut T) -> R;
279
280 /// Convert this mutating function into a `BoxMutatingFunction<T, R>`.
281 ///
282 /// This consuming conversion takes ownership of `self` and returns a
283 /// boxed implementation that forwards calls to the original function.
284 /// Types that can provide a more efficient conversion may override the
285 /// default implementation.
286 ///
287 /// # Consumption
288 ///
289 /// This method consumes the function: the original value will no longer
290 /// be available after the call. For cloneable functions call `.clone()`
291 /// before converting if you need to retain the original instance.
292 ///
293 /// # Returns
294 ///
295 /// A `BoxMutatingFunction<T, R>` that forwards to the original function.
296 ///
297 /// # Examples
298 ///
299 /// ```rust
300 /// use qubit_function::MutatingFunction;
301 ///
302 /// let closure = |x: &mut i32| {
303 /// *x *= 2;
304 /// *x
305 /// };
306 /// let mut boxed = closure.into_box();
307 /// let mut value = 5;
308 /// assert_eq!(boxed.apply(&mut value), 10);
309 /// ```
310 fn into_box(self) -> BoxMutatingFunction<T, R>
311 where
312 Self: Sized + 'static,
313 {
314 BoxMutatingFunction::new(move |t| self.apply(t))
315 }
316
317 /// Convert this mutating function into an `RcMutatingFunction<T, R>`.
318 ///
319 /// This consuming conversion takes ownership of `self` and returns an
320 /// `Rc`-backed function that forwards calls to the original. Override to
321 /// provide a more direct or efficient conversion when available.
322 ///
323 /// # Consumption
324 ///
325 /// This method consumes the function. If you need to keep the original
326 /// instance, clone it prior to calling this method.
327 ///
328 /// # Returns
329 ///
330 /// An `RcMutatingFunction<T, R>` forwarding to the original function.
331 ///
332 /// # Examples
333 ///
334 /// ```rust
335 /// use qubit_function::MutatingFunction;
336 ///
337 /// let closure = |x: &mut i32| {
338 /// *x *= 2;
339 /// *x
340 /// };
341 /// let mut rc = closure.into_rc();
342 /// let mut value = 5;
343 /// assert_eq!(rc.apply(&mut value), 10);
344 /// ```
345 fn into_rc(self) -> RcMutatingFunction<T, R>
346 where
347 Self: Sized + 'static,
348 {
349 RcMutatingFunction::new(move |t| self.apply(t))
350 }
351
352 /// Convert this mutating function into an `ArcMutatingFunction<T, R>`.
353 ///
354 /// This consuming conversion takes ownership of `self` and returns an
355 /// `Arc`-wrapped, thread-safe function. Types may override the default
356 /// implementation to provide a more efficient conversion.
357 ///
358 /// # Consumption
359 ///
360 /// This method consumes the function. Clone the instance first if you
361 /// need to retain the original for further use.
362 ///
363 /// # Returns
364 ///
365 /// An `ArcMutatingFunction<T, R>` that forwards to the original
366 /// function.
367 ///
368 /// # Examples
369 ///
370 /// ```rust
371 /// use qubit_function::MutatingFunction;
372 ///
373 /// let closure = |x: &mut i32| {
374 /// *x *= 2;
375 /// *x
376 /// };
377 /// let mut arc = closure.into_arc();
378 /// let mut value = 5;
379 /// assert_eq!(arc.apply(&mut value), 10);
380 /// ```
381 fn into_arc(self) -> ArcMutatingFunction<T, R>
382 where
383 Self: Sized + Send + Sync + 'static,
384 {
385 ArcMutatingFunction::new(move |t| self.apply(t))
386 }
387
388 /// Consume the function and return an `Fn(&mut T) -> R` closure.
389 ///
390 /// The returned closure forwards calls to the original function and is
391 /// suitable for use with iterator adapters or other contexts expecting
392 /// closures.
393 ///
394 /// # Consumption
395 ///
396 /// This method consumes the function. The original instance will not be
397 /// available after calling this method.
398 ///
399 /// # Returns
400 ///
401 /// A closure implementing `Fn(&mut T) -> R` which forwards to the
402 /// original function.
403 ///
404 /// # Examples
405 ///
406 /// ```rust
407 /// use qubit_function::{MutatingFunction, BoxMutatingFunction};
408 ///
409 /// let func = BoxMutatingFunction::new(|x: &mut i32| {
410 /// *x *= 2;
411 /// *x
412 /// });
413 /// let closure = func.into_fn();
414 /// let mut value = 5;
415 /// assert_eq!(closure(&mut value), 10);
416 /// ```
417 fn into_fn(self) -> impl Fn(&mut T) -> R
418 where
419 Self: Sized + 'static,
420 {
421 move |t| self.apply(t)
422 }
423
424 /// Convert to MutatingFunctionOnce
425 ///
426 /// **⚠️ Consumes `self`**: The original function will be unavailable
427 /// after calling this method.
428 ///
429 /// Converts a reusable mutating function to a one-time function that
430 /// consumes itself on use. This enables passing `MutatingFunction` to
431 /// functions that require `MutatingFunctionOnce`.
432 ///
433 /// # Returns
434 ///
435 /// Returns a `BoxMutatingFunctionOnce<T, R>`
436 ///
437 /// # Examples
438 ///
439 /// ```rust
440 /// use qubit_function::{MutatingFunctionOnce, MutatingFunction,
441 /// ArcMutatingFunction, BoxMutatingFunction};
442 ///
443 /// fn takes_once<F: MutatingFunctionOnce<i32, i32>>(func: F, value: &mut i32) {
444 /// let result = func.apply(value);
445 /// println!("Result: {}", result);
446 /// }
447 ///
448 /// let func = BoxMutatingFunction::new(|x: &mut i32| {
449 /// *x *= 2;
450 /// *x
451 /// });
452 /// let mut value = 5;
453 /// takes_once(func.into_once(), &mut value);
454 /// ```
455 fn into_once(self) -> BoxMutatingFunctionOnce<T, R>
456 where
457 Self: Sized + 'static,
458 {
459 BoxMutatingFunctionOnce::new(move |t| self.apply(t))
460 }
461
462 /// Create a non-consuming `BoxMutatingFunction<T, R>` that forwards to
463 /// `self`.
464 ///
465 /// The default implementation clones `self` (requires `Clone`) and
466 /// returns a boxed function that calls the cloned instance. Override this
467 /// method if a more efficient conversion exists.
468 ///
469 /// # Returns
470 ///
471 /// A `BoxMutatingFunction<T, R>` that forwards to a clone of `self`.
472 fn to_box(&self) -> BoxMutatingFunction<T, R>
473 where
474 Self: Sized + Clone + 'static,
475 {
476 self.clone().into_box()
477 }
478
479 /// Create a non-consuming `RcMutatingFunction<T, R>` that forwards to
480 /// `self`.
481 ///
482 /// The default implementation clones `self` (requires `Clone`) and
483 /// returns an `Rc`-backed function that forwards calls to the clone.
484 /// Override to provide a more direct or efficient conversion if needed.
485 ///
486 /// # Returns
487 ///
488 /// An `RcMutatingFunction<T, R>` that forwards to a clone of `self`.
489 fn to_rc(&self) -> RcMutatingFunction<T, R>
490 where
491 Self: Sized + Clone + 'static,
492 {
493 self.clone().into_rc()
494 }
495
496 /// Create a non-consuming `ArcMutatingFunction<T, R>` that forwards to
497 /// `self`.
498 ///
499 /// The default implementation clones `self` (requires
500 /// `Clone + Send + Sync`) and returns an `Arc`-wrapped function that
501 /// forwards calls to the clone. Override when a more efficient conversion
502 /// is available.
503 ///
504 /// # Returns
505 ///
506 /// An `ArcMutatingFunction<T, R>` that forwards to a clone of `self`.
507 fn to_arc(&self) -> ArcMutatingFunction<T, R>
508 where
509 Self: Sized + Clone + Send + Sync + 'static,
510 {
511 self.clone().into_arc()
512 }
513
514 /// Create a boxed `Fn(&mut T) -> R` closure that forwards to `self`.
515 ///
516 /// The default implementation clones `self` (requires `Clone`) and
517 /// returns a boxed closure that invokes the cloned instance. Override to
518 /// provide a more efficient conversion when possible.
519 ///
520 /// # Returns
521 ///
522 /// A closure implementing `Fn(&mut T) -> R` which forwards to the
523 /// original function.
524 fn to_fn(&self) -> impl Fn(&mut T) -> R
525 where
526 Self: Sized + Clone + 'static,
527 {
528 self.clone().into_fn()
529 }
530
531 /// Convert to MutatingFunctionOnce without consuming self
532 ///
533 /// **⚠️ Requires Clone**: This method requires `Self` to implement `Clone`.
534 /// Clones the current function and converts the clone to a one-time function.
535 ///
536 /// # Returns
537 ///
538 /// Returns a `BoxMutatingFunctionOnce<T, R>`
539 ///
540 /// # Examples
541 ///
542 /// ```rust
543 /// use qubit_function::{MutatingFunctionOnce, MutatingFunction,
544 /// ArcMutatingFunction};
545 ///
546 /// fn takes_once<F: MutatingFunctionOnce<i32, i32>>(func: F, value: &mut i32) {
547 /// let result = func.apply(value);
548 /// println!("Result: {}", result);
549 /// }
550 ///
551 /// let func = ArcMutatingFunction::new(|x: &mut i32| {
552 /// *x *= 2;
553 /// *x
554 /// });
555 /// let mut value = 5;
556 /// takes_once(func.to_once(), &mut value);
557 /// ```
558 fn to_once(&self) -> BoxMutatingFunctionOnce<T, R>
559 where
560 Self: Clone + 'static,
561 {
562 self.clone().into_once()
563 }
564}