qubit_function/transformers/transformer/fn_transformer_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 `FnTransformerOps` public type.
10
11#![allow(unused_imports)]
12
13use super::*;
14
15// ============================================================================
16// FnTransformerOps - Extension trait for closure transformers
17// ============================================================================
18
19/// Extension trait for closures implementing `Fn(T) -> R`
20///
21/// Provides composition methods (`and_then`, `compose`, `when`) for closures
22/// and function pointers without requiring explicit wrapping in
23/// `BoxTransformer`, `RcTransformer`, or `ArcTransformer`.
24///
25/// This trait is automatically implemented for all closures and function
26/// pointers that implement `Fn(T) -> R`.
27///
28/// # Design Rationale
29///
30/// While closures automatically implement `Transformer<T, R>` through blanket
31/// implementation, they don't have access to instance methods like `and_then`,
32/// `compose`, and `when`. This extension trait provides those methods,
33/// returning `BoxTransformer` for maximum flexibility.
34///
35/// # Examples
36///
37/// ## Chain composition with and_then
38///
39/// ```rust
40/// use qubit_function::{Transformer, FnTransformerOps};
41///
42/// let double = |x: i32| x * 2;
43/// let to_string = |x: i32| x.to_string();
44///
45/// let composed = double.and_then(to_string);
46/// assert_eq!(composed.apply(21), "42");
47/// ```
48///
49/// ## Reverse composition with compose
50///
51/// ```rust
52/// use qubit_function::{Transformer, FnTransformerOps};
53///
54/// let double = |x: i32| x * 2;
55/// let add_one = |x: i32| x + 1;
56///
57/// let composed = double.compose(add_one);
58/// assert_eq!(composed.apply(5), 12); // (5 + 1) * 2
59/// ```
60///
61/// ## Conditional transformation with when
62///
63/// ```rust
64/// use qubit_function::{Transformer, FnTransformerOps};
65///
66/// let double = |x: i32| x * 2;
67/// let conditional = double.when(|x: &i32| *x > 0).or_else(|x: i32| -x);
68///
69/// assert_eq!(conditional.apply(5), 10);
70/// assert_eq!(conditional.apply(-5), 5);
71/// ```
72///
73/// # Author
74///
75/// Haixing Hu
76pub trait FnTransformerOps<T, R>: Fn(T) -> R + Sized {
77 /// Chain composition - applies self first, then after
78 ///
79 /// Creates a new transformer that applies this transformer first, then
80 /// applies the after transformer to the result. Consumes self and returns
81 /// a `BoxTransformer`.
82 ///
83 /// # Type Parameters
84 ///
85 /// * `S` - The output type of the after transformer
86 /// * `F` - The type of the after transformer (must implement Transformer<R, S>)
87 ///
88 /// # Parameters
89 ///
90 /// * `after` - The transformer to apply after self. **Note: This parameter
91 /// is passed by value and will transfer ownership.** If you need to
92 /// preserve the original transformer, clone it first (if it implements
93 /// `Clone`). Can be:
94 /// - A closure: `|x: R| -> S`
95 /// - A function pointer: `fn(R) -> S`
96 /// - A `BoxTransformer<R, S>`
97 /// - An `RcTransformer<R, S>`
98 /// - An `ArcTransformer<R, S>`
99 /// - Any type implementing `Transformer<R, S>`
100 ///
101 /// # Returns
102 ///
103 /// A new `BoxTransformer<T, S>` representing the composition
104 ///
105 /// # Examples
106 ///
107 /// ## Direct value passing (ownership transfer)
108 ///
109 /// ```rust
110 /// use qubit_function::{Transformer, FnTransformerOps, BoxTransformer};
111 ///
112 /// let double = |x: i32| x * 2;
113 /// let to_string = BoxTransformer::new(|x: i32| x.to_string());
114 ///
115 /// // to_string is moved here
116 /// let composed = double.and_then(to_string);
117 /// assert_eq!(composed.apply(21), "42");
118 /// // to_string.apply(5); // Would not compile - moved
119 /// ```
120 ///
121 /// ## Preserving original with separate closures
122 ///
123 /// ```rust
124 /// use qubit_function::{Transformer, FnTransformerOps};
125 ///
126 /// let double = |x: i32| x * 2;
127 /// let to_string = |x: i32| x.to_string();
128 /// let to_string_for_validation = |x: i32| x.to_string();
129 ///
130 /// let composed = double.and_then(to_string);
131 /// assert_eq!(composed.apply(21), "42");
132 ///
133 /// // Original still usable
134 /// assert_eq!(to_string_for_validation(5), "5");
135 /// ```
136 fn and_then<S, F>(self, after: F) -> BoxTransformer<T, S>
137 where
138 Self: 'static,
139 S: 'static,
140 F: Transformer<R, S> + 'static,
141 T: 'static,
142 R: 'static,
143 {
144 BoxTransformer::new(move |x: T| after.apply(self(x)))
145 }
146
147 /// Reverse composition - applies before first, then self
148 ///
149 /// Creates a new transformer that applies the before transformer first,
150 /// then applies this transformer to the result. Consumes self and returns
151 /// a `BoxTransformer`.
152 ///
153 /// # Type Parameters
154 ///
155 /// * `S` - The input type of the before transformer
156 /// * `F` - The type of the before transformer (must implement Transformer<S, T>)
157 ///
158 /// # Parameters
159 ///
160 /// * `before` - The transformer to apply before self. **Note: This parameter
161 /// is passed by value and will transfer ownership.** If you need to
162 /// preserve the original transformer, clone it first (if it implements
163 /// `Clone`). Can be:
164 /// - A closure: `|x: S| -> T`
165 /// - A function pointer: `fn(S) -> T`
166 /// - A `BoxTransformer<S, T>`
167 /// - An `RcTransformer<S, T>`
168 /// - An `ArcTransformer<S, T>`
169 /// - Any type implementing `Transformer<S, T>`
170 ///
171 /// # Returns
172 ///
173 /// A new `BoxTransformer<S, R>` representing the composition
174 ///
175 /// # Examples
176 ///
177 /// ## Direct value passing (ownership transfer)
178 ///
179 /// ```rust
180 /// use qubit_function::{Transformer, FnTransformerOps, BoxTransformer};
181 ///
182 /// let double = |x: i32| x * 2;
183 /// let add_one = BoxTransformer::new(|x: i32| x + 1);
184 ///
185 /// // add_one is moved here
186 /// let composed = double.compose(add_one);
187 /// assert_eq!(composed.apply(5), 12); // (5 + 1) * 2
188 /// // add_one.apply(3); // Would not compile - moved
189 /// ```
190 ///
191 /// ## Preserving original with separate closures
192 ///
193 /// ```rust
194 /// use qubit_function::{Transformer, FnTransformerOps};
195 ///
196 /// let double = |x: i32| x * 2;
197 /// let add_one = |x: i32| x + 1;
198 /// let add_one_for_validation = |x: i32| x + 1;
199 ///
200 /// let composed = double.compose(add_one);
201 /// assert_eq!(composed.apply(5), 12); // (5 + 1) * 2
202 ///
203 /// // Original still usable
204 /// assert_eq!(add_one_for_validation(3), 4);
205 /// ```
206 fn compose<S, F>(self, before: F) -> BoxTransformer<S, R>
207 where
208 Self: 'static,
209 S: 'static,
210 F: Transformer<S, T> + 'static,
211 T: 'static,
212 R: 'static,
213 {
214 BoxTransformer::new(move |x: S| self(before.apply(x)))
215 }
216
217 /// Creates a conditional transformer
218 ///
219 /// Returns a transformer that only executes when a predicate is satisfied.
220 /// You must call `or_else()` to provide an alternative transformer for when
221 /// the condition is not satisfied.
222 ///
223 /// # Parameters
224 ///
225 /// * `predicate` - The condition to check. **Note: This parameter is passed
226 /// by value and will transfer ownership.** If you need to preserve the
227 /// original predicate, clone it first (if it implements `Clone`). Can be:
228 /// - A closure: `|x: &T| -> bool`
229 /// - A function pointer: `fn(&T) -> bool`
230 /// - A `BoxPredicate<T>`
231 /// - An `RcPredicate<T>`
232 /// - An `ArcPredicate<T>`
233 /// - Any type implementing `Predicate<T>`
234 ///
235 /// # Returns
236 ///
237 /// Returns `BoxConditionalTransformer<T, R>`
238 ///
239 /// # Examples
240 ///
241 /// ## Basic usage with or_else
242 ///
243 /// ```rust
244 /// use qubit_function::{Transformer, FnTransformerOps};
245 ///
246 /// let double = |x: i32| x * 2;
247 /// let conditional = double.when(|x: &i32| *x > 0).or_else(|x: i32| -x);
248 ///
249 /// assert_eq!(conditional.apply(5), 10);
250 /// assert_eq!(conditional.apply(-5), 5);
251 /// ```
252 ///
253 /// ## Preserving original with separate predicates
254 ///
255 /// ```rust
256 /// use qubit_function::{Transformer, FnTransformerOps};
257 ///
258 /// let double = |x: i32| x * 2;
259 /// let is_positive = |x: &i32| *x > 0;
260 /// let is_positive_for_validation = |x: &i32| *x > 0;
261 /// let conditional = double.when(is_positive)
262 /// .or_else(|x: i32| -x);
263 ///
264 /// assert_eq!(conditional.apply(5), 10);
265 ///
266 /// // Original predicate still usable
267 /// assert!(is_positive_for_validation(&3));
268 /// ```
269 fn when<P>(self, predicate: P) -> BoxConditionalTransformer<T, R>
270 where
271 Self: 'static,
272 P: Predicate<T> + 'static,
273 T: 'static,
274 R: 'static,
275 {
276 BoxTransformer::new(self).when(predicate)
277 }
278}
279
280/// Blanket implementation of FnTransformerOps for all closures
281///
282/// Automatically implements `FnTransformerOps<T, R>` for any type that
283/// implements `Fn(T) -> R`.
284///
285/// # Author
286///
287/// Haixing Hu
288impl<T, R, F> FnTransformerOps<T, R> for F where F: Fn(T) -> R {}