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!(" BoxStatefulTransformer consumed once: {}", box_mapper.apply(10)); // 10 * 1 = 10
151
152 // RcStatefulTransformer can be consumed as TransformerOnce
153 let mut counter = 0;
154 let mut rc_mapper = RcStatefulTransformer::new(move |x: i32| {
155 counter += 1;
156 x + counter
157 });
158 let rc_clone = rc_mapper.clone(); // Clone before consuming
159 println!(" RcStatefulTransformer consumed once: {}", rc_mapper.apply(10)); // 10 + 1 = 11
160 println!(" RcStatefulTransformer clone still works: {}", {
161 let mut rc_clone_for_call = rc_clone.clone();
162 rc_clone_for_call.apply(10)
163 }); // 10 + 2 = 12
164
165 // ArcStatefulTransformer can be consumed as TransformerOnce
166 let mut counter = 0;
167 let mut arc_mapper = ArcStatefulTransformer::new(move |x: i32| {
168 counter += 1;
169 x * counter
170 });
171 let arc_clone = arc_mapper.clone(); // Clone before consuming
172 println!(" ArcStatefulTransformer consumed once: {}", arc_mapper.apply(10)); // 10 * 1 = 10
173 println!(" ArcStatefulTransformer clone still works: {}", {
174 let mut arc_clone_for_call = arc_clone.clone();
175 arc_clone_for_call.apply(10)
176 }); // 10 * 2 = 20
177
178 // 8. Converting to BoxTransformerOnce
179 println!("\n8. Converting StatefulTransformers to BoxTransformerOnce:");
180
181 let mut counter = 0;
182 let mapper = BoxStatefulTransformer::new(move |x: i32| {
183 counter += 1;
184 x * counter
185 });
186 let mut once_mapper = mapper.into_box();
187 println!(" BoxStatefulTransformer->BoxTransformerOnce: {}", once_mapper.apply(5)); // 5 * 1 = 5
188
189 // RcStatefulTransformer can use to_box() to preserve original
190 let mut counter = 0;
191 let rc_mapper = RcStatefulTransformer::new(move |x: i32| {
192 counter += 1;
193 x * counter
194 });
195 let mut once_mapper = rc_mapper.to_box();
196 println!(" RcStatefulTransformer->BoxTransformerOnce: {}", once_mapper.apply(5)); // 5 * 1 = 5
197 println!(" Original RcStatefulTransformer still works: {}", {
198 let mut rc_original_for_call = rc_mapper.clone();
199 rc_original_for_call.apply(5)
200 }); // 5 * 2 = 10
201
202 println!("\n=== Demo Complete ===");
203}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".
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.