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 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 FnMut(T) -> R

Provides composition methods (and_then, compose, when) for closures without requiring explicit wrapping in BoxStatefulTransformer, RcStatefulTransformer, or ArcStatefulTransformer.

This trait is automatically implemented for all closures that implement FnMut(T) -> R.

§Design Rationale

While closures automatically implement StatefulTransformer<T, R> through blanket implementation, they don’t have access to instance methods like and_then, compose, and when. This extension trait provides those methods, returning BoxStatefulTransformer for maximum flexibility.

§Examples

§Chain composition with and_then

use qubit_function::{StatefulTransformer, FnStatefulTransformerOps, FnTransformerOps, Transformer};

let mut counter1 = 0;
let transformer1 = move |x: i32| {
    counter1 += 1;
    x + counter1
};

let mut counter2 = 0;
let transformer2 = move |x: i32| {
    counter2 += 1;
    x * counter2
};

let mut composed = FnStatefulTransformerOps::and_then(transformer1, transformer2);
assert_eq!(composed.apply(10), 11);  // (10 + 1) * 1

§Reverse composition with compose

use qubit_function::{StatefulTransformer, FnStatefulTransformerOps, FnTransformerOps, Transformer};

let transformer = |x: i32| x * 2;

let mut composed = transformer.compose(|x: i32| x + 1);
assert_eq!(composed.apply(10), 22); // (10 + 1) * 2

§Conditional mapping with when

use qubit_function::{StatefulTransformer, FnStatefulTransformerOps};

let mut transformer = (|x: i32| x * 2)
    .when(|x: &i32| *x > 0)
    .or_else(|x: i32| -x);

assert_eq!(transformer.apply(5), 10);
assert_eq!(transformer.apply(-5), 5);

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 BoxStatefulTransformer.

§Type Parameters
  • S - The output type of the after transformer
  • F - The type of the after transformer (must implement StatefulTransformer<R, S>)
§Parameters
  • after - The transformer to apply after self. Can be:
    • A closure: |x: R| -> S
    • A BoxStatefulTransformer<R, S>
    • An RcStatefulTransformer<R, S>
    • An ArcStatefulTransformer<R, S>
    • Any type implementing StatefulTransformer<R, S>
§Returns

A new BoxStatefulTransformer<T, S> representing the composition

§Examples
use qubit_function::{StatefulTransformer, FnStatefulTransformerOps, BoxStatefulTransformer};

let mut counter1 = 0;
let transformer1 = move |x: i32| {
    counter1 += 1;
    x + counter1
};

let mut counter2 = 0;
let transformer2 = BoxStatefulTransformer::new(move |x: i32| {
    counter2 += 1;
    x * counter2
});

let mut composed = transformer1.and_then(transformer2);
assert_eq!(composed.apply(10), 11);
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 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. 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 BoxConditionalStatefulTransformer<T, R>

§Examples
use qubit_function::{StatefulTransformer, FnStatefulTransformerOps};

let mut transformer = (|x: i32| x * 2)
    .when(|x: &i32| *x > 0)
    .or_else(|x: i32| -x);

assert_eq!(transformer.apply(5), 10);
assert_eq!(transformer.apply(-5), 5);

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 of FnStatefulTransformerOps for all closures

Automatically implements FnStatefulTransformerOps<T, R> for any type that implements FnMut(T) -> R.