pub trait FnTransformerOps<T, R>: Fn(T) -> R + Sized {
// Provided methods
fn and_then<S, F>(self, after: F) -> BoxTransformer<T, S>
where Self: 'static,
S: 'static,
F: Transformer<R, S> + 'static,
T: 'static,
R: 'static { ... }
fn compose<S, F>(self, before: F) -> BoxTransformer<S, R>
where Self: 'static,
S: 'static,
F: Transformer<S, T> + 'static,
T: 'static,
R: 'static { ... }
fn when<P>(self, predicate: P) -> BoxConditionalTransformer<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) -> BoxTransformer<T, S>where
Self: 'static,
S: 'static,
F: Transformer<R, S> + 'static,
T: 'static,
R: 'static,
fn and_then<S, F>(self, after: F) -> BoxTransformer<T, S>where
Self: 'static,
S: 'static,
F: Transformer<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?
20fn main() {
21 println!("=== FnTransformerOps Example ===\n");
22
23 // 1. Basic and_then composition
24 println!("1. Basic and_then composition:");
25 let double = |x: i32| x * 2;
26 let to_string = |x: i32| x.to_string();
27 let composed = double.and_then(to_string);
28 println!(
29 " double.and_then(to_string).apply(21) = {}",
30 composed.apply(21)
31 );
32 println!();
33
34 // 2. Chained and_then composition
35 println!("2. Chained and_then composition:");
36 let add_one = |x: i32| x + 1;
37 let double = |x: i32| x * 2;
38 let to_string = |x: i32| x.to_string();
39 let chained = add_one.and_then(double).and_then(to_string);
40 println!(
41 " add_one.and_then(double).and_then(to_string).apply(5) = {}",
42 chained.apply(5)
43 ); // (5 + 1) * 2 = 12
44 println!();
45
46 // 3. compose reverse composition
47 println!("3. compose reverse composition:");
48 let double = |x: i32| x * 2;
49 let add_one = |x: i32| x + 1;
50 let composed = double.compose(add_one);
51 println!(
52 " double.compose(add_one).apply(5) = {}",
53 composed.apply(5)
54 ); // (5 + 1) * 2 = 12
55 println!();
56
57 // 4. Conditional transformation when
58 println!("4. Conditional transformation when:");
59 let double = |x: i32| x * 2;
60 let conditional = double.when(|x: &i32| *x > 0).or_else(|x: i32| -x);
61 println!(" double.when(x > 0).or_else(negate):");
62 println!(" transform(5) = {}", conditional.apply(5)); // 10
63 println!(" transform(-5) = {}", conditional.apply(-5)); // 5
64 println!();
65
66 // 5. Complex composition
67 println!("5. Complex composition:");
68 let add_one = |x: i32| x + 1;
69 let double = |x: i32| x * 2;
70 let triple = |x: i32| x * 3;
71 let to_string = |x: i32| x.to_string();
72
73 let complex = add_one
74 .and_then(double.when(|x: &i32| *x > 5).or_else(triple))
75 .and_then(to_string);
76
77 println!(" add_one.and_then(double.when(x > 5).or_else(triple)).and_then(to_string):");
78 println!(" transform(1) = {}", complex.apply(1)); // (1 + 1) = 2 <= 5, so 2 * 3 = 6
79 println!(" transform(5) = {}", complex.apply(5)); // (5 + 1) = 6 > 5, so 6 * 2 = 12
80 println!(" transform(10) = {}", complex.apply(10)); // (10 + 1) = 11 > 5, so 11 * 2 = 22
81 println!();
82
83 // 6. Type conversion
84 println!("6. Type conversion:");
85 let to_string = |x: i32| x.to_string();
86 let get_length = |s: String| s.len();
87 let length_transformer = to_string.and_then(get_length);
88 println!(
89 " to_string.and_then(get_length).apply(12345) = {}",
90 length_transformer.apply(12345)
91 ); // 5
92 println!();
93
94 // 7. Closures that capture environment
95 println!("7. Closures that capture environment:");
96 let multiplier = 3;
97 let multiply = move |x: i32| x * multiplier;
98 let add_ten = |x: i32| x + 10;
99 let with_capture = multiply.and_then(add_ten);
100 println!(
101 " multiply(3).and_then(add_ten).apply(5) = {}",
102 with_capture.apply(5)
103 ); // 5 * 3 + 10 = 25
104 println!();
105
106 // 8. Function pointers
107 println!("8. Function pointers:");
108 fn double_fn(x: i32) -> i32 {
109 x * 2
110 }
111 fn add_one_fn(x: i32) -> i32 {
112 x + 1
113 }
114 let fn_composed = double_fn.and_then(add_one_fn);
115 println!(
116 " double_fn.and_then(add_one_fn).apply(5) = {}",
117 fn_composed.apply(5)
118 ); // 5 * 2 + 1 = 11
119 println!();
120
121 // 9. Multi-conditional transformation
122 println!("9. Multi-conditional transformation:");
123 let abs = |x: i32| x.abs();
124 let double = |x: i32| x * 2;
125 let transformer = abs.when(|x: &i32| *x < 0).or_else(double);
126 println!(" abs.when(x < 0).or_else(double):");
127 println!(" transform(-5) = {}", transformer.apply(-5)); // abs(-5) = 5
128 println!(" transform(5) = {}", transformer.apply(5)); // 5 * 2 = 10
129 println!(" transform(0) = {}", transformer.apply(0)); // 0 * 2 = 0
130 println!();
131
132 println!("=== Example completed ===");
133}Sourcefn compose<S, F>(self, before: F) -> BoxTransformer<S, R>where
Self: 'static,
S: 'static,
F: Transformer<S, T> + 'static,
T: 'static,
R: 'static,
fn compose<S, F>(self, before: F) -> BoxTransformer<S, R>where
Self: 'static,
S: 'static,
F: Transformer<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.
Examples found in repository?
20fn main() {
21 println!("=== FnTransformerOps Example ===\n");
22
23 // 1. Basic and_then composition
24 println!("1. Basic and_then composition:");
25 let double = |x: i32| x * 2;
26 let to_string = |x: i32| x.to_string();
27 let composed = double.and_then(to_string);
28 println!(
29 " double.and_then(to_string).apply(21) = {}",
30 composed.apply(21)
31 );
32 println!();
33
34 // 2. Chained and_then composition
35 println!("2. Chained and_then composition:");
36 let add_one = |x: i32| x + 1;
37 let double = |x: i32| x * 2;
38 let to_string = |x: i32| x.to_string();
39 let chained = add_one.and_then(double).and_then(to_string);
40 println!(
41 " add_one.and_then(double).and_then(to_string).apply(5) = {}",
42 chained.apply(5)
43 ); // (5 + 1) * 2 = 12
44 println!();
45
46 // 3. compose reverse composition
47 println!("3. compose reverse composition:");
48 let double = |x: i32| x * 2;
49 let add_one = |x: i32| x + 1;
50 let composed = double.compose(add_one);
51 println!(
52 " double.compose(add_one).apply(5) = {}",
53 composed.apply(5)
54 ); // (5 + 1) * 2 = 12
55 println!();
56
57 // 4. Conditional transformation when
58 println!("4. Conditional transformation when:");
59 let double = |x: i32| x * 2;
60 let conditional = double.when(|x: &i32| *x > 0).or_else(|x: i32| -x);
61 println!(" double.when(x > 0).or_else(negate):");
62 println!(" transform(5) = {}", conditional.apply(5)); // 10
63 println!(" transform(-5) = {}", conditional.apply(-5)); // 5
64 println!();
65
66 // 5. Complex composition
67 println!("5. Complex composition:");
68 let add_one = |x: i32| x + 1;
69 let double = |x: i32| x * 2;
70 let triple = |x: i32| x * 3;
71 let to_string = |x: i32| x.to_string();
72
73 let complex = add_one
74 .and_then(double.when(|x: &i32| *x > 5).or_else(triple))
75 .and_then(to_string);
76
77 println!(" add_one.and_then(double.when(x > 5).or_else(triple)).and_then(to_string):");
78 println!(" transform(1) = {}", complex.apply(1)); // (1 + 1) = 2 <= 5, so 2 * 3 = 6
79 println!(" transform(5) = {}", complex.apply(5)); // (5 + 1) = 6 > 5, so 6 * 2 = 12
80 println!(" transform(10) = {}", complex.apply(10)); // (10 + 1) = 11 > 5, so 11 * 2 = 22
81 println!();
82
83 // 6. Type conversion
84 println!("6. Type conversion:");
85 let to_string = |x: i32| x.to_string();
86 let get_length = |s: String| s.len();
87 let length_transformer = to_string.and_then(get_length);
88 println!(
89 " to_string.and_then(get_length).apply(12345) = {}",
90 length_transformer.apply(12345)
91 ); // 5
92 println!();
93
94 // 7. Closures that capture environment
95 println!("7. Closures that capture environment:");
96 let multiplier = 3;
97 let multiply = move |x: i32| x * multiplier;
98 let add_ten = |x: i32| x + 10;
99 let with_capture = multiply.and_then(add_ten);
100 println!(
101 " multiply(3).and_then(add_ten).apply(5) = {}",
102 with_capture.apply(5)
103 ); // 5 * 3 + 10 = 25
104 println!();
105
106 // 8. Function pointers
107 println!("8. Function pointers:");
108 fn double_fn(x: i32) -> i32 {
109 x * 2
110 }
111 fn add_one_fn(x: i32) -> i32 {
112 x + 1
113 }
114 let fn_composed = double_fn.and_then(add_one_fn);
115 println!(
116 " double_fn.and_then(add_one_fn).apply(5) = {}",
117 fn_composed.apply(5)
118 ); // 5 * 2 + 1 = 11
119 println!();
120
121 // 9. Multi-conditional transformation
122 println!("9. Multi-conditional transformation:");
123 let abs = |x: i32| x.abs();
124 let double = |x: i32| x * 2;
125 let transformer = abs.when(|x: &i32| *x < 0).or_else(double);
126 println!(" abs.when(x < 0).or_else(double):");
127 println!(" transform(-5) = {}", transformer.apply(-5)); // abs(-5) = 5
128 println!(" transform(5) = {}", transformer.apply(5)); // 5 * 2 = 10
129 println!(" transform(0) = {}", transformer.apply(0)); // 0 * 2 = 0
130 println!();
131
132 println!("=== Example completed ===");
133}Sourcefn when<P>(self, predicate: P) -> BoxConditionalTransformer<T, R>where
Self: 'static,
P: Predicate<T> + 'static,
T: 'static,
R: 'static,
fn when<P>(self, predicate: P) -> BoxConditionalTransformer<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));Examples found in repository?
20fn main() {
21 println!("=== FnTransformerOps Example ===\n");
22
23 // 1. Basic and_then composition
24 println!("1. Basic and_then composition:");
25 let double = |x: i32| x * 2;
26 let to_string = |x: i32| x.to_string();
27 let composed = double.and_then(to_string);
28 println!(
29 " double.and_then(to_string).apply(21) = {}",
30 composed.apply(21)
31 );
32 println!();
33
34 // 2. Chained and_then composition
35 println!("2. Chained and_then composition:");
36 let add_one = |x: i32| x + 1;
37 let double = |x: i32| x * 2;
38 let to_string = |x: i32| x.to_string();
39 let chained = add_one.and_then(double).and_then(to_string);
40 println!(
41 " add_one.and_then(double).and_then(to_string).apply(5) = {}",
42 chained.apply(5)
43 ); // (5 + 1) * 2 = 12
44 println!();
45
46 // 3. compose reverse composition
47 println!("3. compose reverse composition:");
48 let double = |x: i32| x * 2;
49 let add_one = |x: i32| x + 1;
50 let composed = double.compose(add_one);
51 println!(
52 " double.compose(add_one).apply(5) = {}",
53 composed.apply(5)
54 ); // (5 + 1) * 2 = 12
55 println!();
56
57 // 4. Conditional transformation when
58 println!("4. Conditional transformation when:");
59 let double = |x: i32| x * 2;
60 let conditional = double.when(|x: &i32| *x > 0).or_else(|x: i32| -x);
61 println!(" double.when(x > 0).or_else(negate):");
62 println!(" transform(5) = {}", conditional.apply(5)); // 10
63 println!(" transform(-5) = {}", conditional.apply(-5)); // 5
64 println!();
65
66 // 5. Complex composition
67 println!("5. Complex composition:");
68 let add_one = |x: i32| x + 1;
69 let double = |x: i32| x * 2;
70 let triple = |x: i32| x * 3;
71 let to_string = |x: i32| x.to_string();
72
73 let complex = add_one
74 .and_then(double.when(|x: &i32| *x > 5).or_else(triple))
75 .and_then(to_string);
76
77 println!(" add_one.and_then(double.when(x > 5).or_else(triple)).and_then(to_string):");
78 println!(" transform(1) = {}", complex.apply(1)); // (1 + 1) = 2 <= 5, so 2 * 3 = 6
79 println!(" transform(5) = {}", complex.apply(5)); // (5 + 1) = 6 > 5, so 6 * 2 = 12
80 println!(" transform(10) = {}", complex.apply(10)); // (10 + 1) = 11 > 5, so 11 * 2 = 22
81 println!();
82
83 // 6. Type conversion
84 println!("6. Type conversion:");
85 let to_string = |x: i32| x.to_string();
86 let get_length = |s: String| s.len();
87 let length_transformer = to_string.and_then(get_length);
88 println!(
89 " to_string.and_then(get_length).apply(12345) = {}",
90 length_transformer.apply(12345)
91 ); // 5
92 println!();
93
94 // 7. Closures that capture environment
95 println!("7. Closures that capture environment:");
96 let multiplier = 3;
97 let multiply = move |x: i32| x * multiplier;
98 let add_ten = |x: i32| x + 10;
99 let with_capture = multiply.and_then(add_ten);
100 println!(
101 " multiply(3).and_then(add_ten).apply(5) = {}",
102 with_capture.apply(5)
103 ); // 5 * 3 + 10 = 25
104 println!();
105
106 // 8. Function pointers
107 println!("8. Function pointers:");
108 fn double_fn(x: i32) -> i32 {
109 x * 2
110 }
111 fn add_one_fn(x: i32) -> i32 {
112 x + 1
113 }
114 let fn_composed = double_fn.and_then(add_one_fn);
115 println!(
116 " double_fn.and_then(add_one_fn).apply(5) = {}",
117 fn_composed.apply(5)
118 ); // 5 * 2 + 1 = 11
119 println!();
120
121 // 9. Multi-conditional transformation
122 println!("9. Multi-conditional transformation:");
123 let abs = |x: i32| x.abs();
124 let double = |x: i32| x * 2;
125 let transformer = abs.when(|x: &i32| *x < 0).or_else(double);
126 println!(" abs.when(x < 0).or_else(double):");
127 println!(" transform(-5) = {}", transformer.apply(-5)); // abs(-5) = 5
128 println!(" transform(5) = {}", transformer.apply(5)); // 5 * 2 = 10
129 println!(" transform(0) = {}", transformer.apply(0)); // 0 * 2 = 0
130 println!();
131
132 println!("=== Example completed ===");
133}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> FnTransformerOps<T, R> for Fwhere
F: Fn(T) -> R,
Blanket implementation for all closures
Automatically implements the extension trait for any type that implements the base transformer trait.