Skip to main content

FnStatefulTransformerOps

Trait FnStatefulTransformerOps 

Source
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§

Source

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 transformer
  • F - 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 implements Clone). 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?
examples/transformers/stateful_transformer_demo.rs (line 111)
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}
Source

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 transformer
  • F - The type of the before transformer
§Parameters
  • before - The transformer to apply before self.
§Returns

A new Box-based transformer representing the reverse composition.

Source

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 implements Clone). 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>
§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§

Source§

impl<T, R, F> FnStatefulTransformerOps<T, R> for F
where F: FnMut(T) -> R,

Blanket implementation for all closures

Automatically implements the extension trait for any type that implements the base transformer trait.