pub trait FnStatefulTransformerOps<T, R>: FnMut(T) -> R + Sized {
// Provided methods
fn and_then<S, F>(self, after: F) -> BoxStatefulTransformer<T, S>
where Self: 'static,
S: 'static,
F: StatefulTransformer<R, S> + 'static,
T: 'static,
R: 'static { ... }
fn compose<S, F>(self, before: F) -> BoxStatefulTransformer<S, R>
where Self: 'static,
S: 'static,
F: StatefulTransformer<S, T> + 'static,
T: 'static,
R: 'static { ... }
fn when<P>(self, predicate: P) -> BoxConditionalStatefulTransformer<T, R>
where Self: 'static,
P: Predicate<T> + 'static,
T: 'static,
R: 'static { ... }
}Expand description
Extension trait for closures implementing the base transformer trait
Provides composition methods (and_then, compose, when) for closures
and function pointers without requiring explicit wrapping.
This trait is automatically implemented for all closures and function pointers that implement the base transformer trait.
§Design Rationale
While closures automatically implement the base transformer trait
through blanket implementation, they don’t have access to instance
methods like and_then, compose, and when. This extension trait
provides those methods, returning the appropriate Box-based
transformer type for maximum flexibility.
Provided Methods§
Sourcefn and_then<S, F>(self, after: F) -> BoxStatefulTransformer<T, S>where
Self: 'static,
S: 'static,
F: StatefulTransformer<R, S> + 'static,
T: 'static,
R: 'static,
fn and_then<S, F>(self, after: F) -> BoxStatefulTransformer<T, S>where
Self: 'static,
S: 'static,
F: StatefulTransformer<R, S> + 'static,
T: 'static,
R: 'static,
Chain composition - applies self first, then after
Creates a new transformer that applies this transformer first, then applies the after transformer to the result. Consumes self and returns a Box-based transformer.
§Type Parameters
S- The output type of the after transformerF- The type of the after transformer (must implement the transformer trait)
§Parameters
after- The transformer to apply after self. Note: This parameter is passed by value and will transfer ownership. If you need to preserve the original transformer, clone it first (if it implementsClone). Can be:- A closure
- A function pointer
- A Box-based transformer
- An Rc-based transformer
- An Arc-based transformer
- Any type implementing the transformer trait
§Returns
A new Box-based transformer representing the composition
§Examples
§Direct value passing (ownership transfer)
use qubit_function::{BoxTransformer, FnTransformerOps, Transformer};
let double = |x: i32| x * 2;
let to_string = BoxTransformer::new(|x: i32| x.to_string());
// to_string is moved here
let composed = double.and_then(to_string);
assert_eq!(composed.apply(21), "42");
// to_string.apply(5); // Would not compile - moved§Preserving behavior with separate closures
use qubit_function::{BoxTransformer, FnTransformerOps, Transformer};
let double = |x: i32| x * 2;
let to_string_for_validation = |x: i32| x.to_string();
let composed = double.and_then(BoxTransformer::new(|x: i32| x.to_string()));
assert_eq!(composed.apply(21), "42");
assert_eq!(to_string_for_validation(5), "5");Examples found in repository?
24fn main() {
25 println!("=== StatefulTransformer Demo ===\n");
26
27 // 1. Basic BoxStatefulTransformer with state
28 println!("1. BoxStatefulTransformer with stateful counter:");
29 let mut counter = 0;
30 let mut mapper = BoxStatefulTransformer::new(move |x: i32| {
31 counter += 1;
32 format!("Item #{}: {}", counter, x)
33 });
34
35 println!(" {}", mapper.apply(100)); // Item #1: 100
36 println!(" {}", mapper.apply(200)); // Item #2: 200
37 println!(" {}", mapper.apply(300)); // Item #3: 300
38
39 // 2. Composing mappers with and_then
40 println!("\n2. Composing mappers with and_then:");
41 let mut counter1 = 0;
42 let mapper1 = BoxStatefulTransformer::new(move |x: i32| {
43 counter1 += 1;
44 x + counter1
45 });
46
47 let mut counter2 = 0;
48 let mapper2 = BoxStatefulTransformer::new(move |x: i32| {
49 counter2 += 1;
50 x * counter2
51 });
52
53 let mut composed = mapper1.and_then(mapper2);
54 println!(" First call: {}", composed.apply(10)); // (10 + 1) * 1 = 11
55 println!(" Second call: {}", composed.apply(10)); // (10 + 2) * 2 = 24
56 println!(" Third call: {}", composed.apply(10)); // (10 + 3) * 3 = 39
57
58 // 3. Conditional mapping with when/or_else
59 println!("\n3. Conditional mapping:");
60 let mut high_count = 0;
61 let mut low_count = 0;
62
63 let mut conditional = BoxStatefulTransformer::new(move |x: i32| {
64 high_count += 1;
65 format!("High[{}]: {} * 2 = {}", high_count, x, x * 2)
66 })
67 .when(|x: &i32| *x >= 10)
68 .or_else(move |x| {
69 low_count += 1;
70 format!("Low[{}]: {} + 1 = {}", low_count, x, x + 1)
71 });
72
73 println!(" {}", conditional.apply(15)); // High[1]: 15 * 2 = 30
74 println!(" {}", conditional.apply(5)); // Low[1]: 5 + 1 = 6
75 println!(" {}", conditional.apply(20)); // High[2]: 20 * 2 = 40
76
77 // 4. RcStatefulTransformer for cloneable mappers
78 println!("\n4. RcStatefulTransformer (cloneable, single-threaded):");
79 let mut counter = 0;
80 let mapper = RcStatefulTransformer::new(move |x: i32| {
81 counter += 1;
82 x + counter
83 });
84
85 let mut mapper1 = mapper.clone();
86 let mut mapper2 = mapper.clone();
87
88 println!(" mapper1: {}", mapper1.apply(10)); // 11
89 println!(" mapper2: {}", mapper2.apply(10)); // 12
90 println!(" mapper1: {}", mapper1.apply(10)); // 13
91
92 // 5. ArcStatefulTransformer for thread-safe mappers
93 println!("\n5. ArcStatefulTransformer (thread-safe):");
94 let mut counter = 0;
95 let mapper = ArcStatefulTransformer::new(move |x: i32| {
96 counter += 1;
97 format!("Result[{}]: {}", counter, x * 2)
98 });
99
100 let mut mapper_clone = mapper.clone();
101 println!(" Original: {}", mapper_clone.apply(5)); // Result[1]: 10
102 println!(" Clone: {}", mapper_clone.apply(7)); // Result[2]: 14
103
104 // 6. Using FnStatefulTransformerOps extension trait
105 println!("\n6. Using FnStatefulTransformerOps extension trait:");
106 let mut count = 0;
107 let mut mapper = (move |x: i32| {
108 count += 1;
109 x + count
110 })
111 .and_then(|x| x * 2);
112
113 println!(" {}", mapper.apply(10)); // (10 + 1) * 2 = 22
114 println!(" {}", mapper.apply(10)); // (10 + 2) * 2 = 24
115
116 // 7. Building a complex pipeline
117 println!("\n7. Complex processing pipeline:");
118 let mut step1_count = 0;
119 let step1 = BoxStatefulTransformer::new(move |x: i32| {
120 step1_count += 1;
121 format!("Step1[{}]: {}", step1_count, x)
122 });
123
124 let mut step2_count = 0;
125 let step2 = BoxStatefulTransformer::new(move |s: String| {
126 step2_count += 1;
127 format!("{} -> Step2[{}]", s, step2_count)
128 });
129
130 let mut step3_count = 0;
131 let step3 = BoxStatefulTransformer::new(move |s: String| {
132 step3_count += 1;
133 format!("{} -> Step3[{}]", s, step3_count)
134 });
135
136 let mut pipeline = step1.and_then(step2).and_then(step3);
137
138 println!(" {}", pipeline.apply(100));
139 println!(" {}", pipeline.apply(200));
140
141 // 7. TransformerOnce implementation - consuming transformers
142 println!("\n7. TransformerOnce implementation - consuming StatefulTransformers:");
143
144 // BoxStatefulTransformer can be consumed as TransformerOnce
145 let mut counter = 0;
146 let mut box_mapper = BoxStatefulTransformer::new(move |x: i32| {
147 counter += 1;
148 x * counter
149 });
150 println!(
151 " BoxStatefulTransformer consumed once: {}",
152 box_mapper.apply(10)
153 ); // 10 * 1 = 10
154
155 // RcStatefulTransformer can be consumed as TransformerOnce
156 let mut counter = 0;
157 let mut rc_mapper = RcStatefulTransformer::new(move |x: i32| {
158 counter += 1;
159 x + counter
160 });
161 let rc_clone = rc_mapper.clone(); // Clone before consuming
162 println!(
163 " RcStatefulTransformer consumed once: {}",
164 rc_mapper.apply(10)
165 ); // 10 + 1 = 11
166 println!(" RcStatefulTransformer clone still works: {}", {
167 let mut rc_clone_for_call = rc_clone.clone();
168 rc_clone_for_call.apply(10)
169 }); // 10 + 2 = 12
170
171 // ArcStatefulTransformer can be consumed as TransformerOnce
172 let mut counter = 0;
173 let mut arc_mapper = ArcStatefulTransformer::new(move |x: i32| {
174 counter += 1;
175 x * counter
176 });
177 let arc_clone = arc_mapper.clone(); // Clone before consuming
178 println!(
179 " ArcStatefulTransformer consumed once: {}",
180 arc_mapper.apply(10)
181 ); // 10 * 1 = 10
182 println!(" ArcStatefulTransformer clone still works: {}", {
183 let mut arc_clone_for_call = arc_clone.clone();
184 arc_clone_for_call.apply(10)
185 }); // 10 * 2 = 20
186
187 // 8. Converting to BoxTransformerOnce
188 println!("\n8. Converting StatefulTransformers to BoxTransformerOnce:");
189
190 let mut counter = 0;
191 let mapper = BoxStatefulTransformer::new(move |x: i32| {
192 counter += 1;
193 x * counter
194 });
195 let mut once_mapper = mapper.into_box();
196 println!(
197 " BoxStatefulTransformer->BoxTransformerOnce: {}",
198 once_mapper.apply(5)
199 ); // 5 * 1 = 5
200
201 // RcStatefulTransformer can use to_box() to preserve original
202 let mut counter = 0;
203 let rc_mapper = RcStatefulTransformer::new(move |x: i32| {
204 counter += 1;
205 x * counter
206 });
207 let mut once_mapper = rc_mapper.to_box();
208 println!(
209 " RcStatefulTransformer->BoxTransformerOnce: {}",
210 once_mapper.apply(5)
211 ); // 5 * 1 = 5
212 println!(" Original RcStatefulTransformer still works: {}", {
213 let mut rc_original_for_call = rc_mapper.clone();
214 rc_original_for_call.apply(5)
215 }); // 5 * 2 = 10
216
217 println!("\n=== Demo Complete ===");
218}Sourcefn compose<S, F>(self, before: F) -> BoxStatefulTransformer<S, R>where
Self: 'static,
S: 'static,
F: StatefulTransformer<S, T> + 'static,
T: 'static,
R: 'static,
fn compose<S, F>(self, before: F) -> BoxStatefulTransformer<S, R>where
Self: 'static,
S: 'static,
F: StatefulTransformer<S, T> + 'static,
T: 'static,
R: 'static,
Reverse composition - applies before first, then self.
Creates a new transformer that applies the before transformer first, then applies this transformer to the result. Consumes self and returns a Box-based transformer.
§Type Parameters
S- The input type of the before transformerF- The type of the before transformer
§Parameters
before- The transformer to apply before self.
§Returns
A new Box-based transformer representing the reverse composition.
Sourcefn when<P>(self, predicate: P) -> BoxConditionalStatefulTransformer<T, R>where
Self: 'static,
P: Predicate<T> + 'static,
T: 'static,
R: 'static,
fn when<P>(self, predicate: P) -> BoxConditionalStatefulTransformer<T, R>where
Self: 'static,
P: Predicate<T> + 'static,
T: 'static,
R: 'static,
Creates a conditional transformer
Returns a transformer that only executes when a predicate is satisfied.
You must call or_else() to provide an alternative transformer for when
the condition is not satisfied.
§Parameters
predicate- The condition to check. Note: This parameter is passed by value and will transfer ownership. If you need to preserve the original predicate, clone it first (if it implementsClone). Can be:- A closure:
|x: &T| -> bool - A function pointer:
fn(&T) -> bool - A
BoxPredicate<T> - An
RcPredicate<T> - An
ArcPredicate<T> - Any type implementing
Predicate<T>
- A closure:
§Returns
Returns the appropriate conditional transformer type
§Examples
§Basic usage with or_else
use qubit_function::{Transformer, FnTransformerOps};
let double = |x: i32| x * 2;
let conditional = double.when(|x: &i32| *x > 0).or_else(|x: i32| -x);
assert_eq!(conditional.apply(5), 10);
assert_eq!(conditional.apply(-5), 5);§Reusing equivalent predicate logic
use qubit_function::{FnTransformerOps, Transformer};
let double = |x: i32| x * 2;
let is_positive_for_validation = |x: &i32| *x > 0;
let conditional = double.when(|x: &i32| *x > 0)
.or_else(|x: i32| -x);
assert_eq!(conditional.apply(5), 10);
assert!(is_positive_for_validation(&3));Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.
Implementors§
impl<T, R, F> FnStatefulTransformerOps<T, R> for Fwhere
F: FnMut(T) -> R,
Blanket implementation for all closures
Automatically implements the extension trait for any type that implements the base transformer trait.