pub struct ArcBiTransformer<T, U, R> { /* private fields */ }Expand description
ArcBiTransformer - thread-safe bi-transformer wrapper
A thread-safe, clonable bi-transformer wrapper suitable for multi-threaded scenarios. Can be called multiple times and shared across threads.
§Features
- Based on:
Arc<dyn Fn(T, U) -> R + Send + Sync> - Ownership: Shared ownership via reference counting
- Reusability: Can be called multiple times (each call consumes its inputs)
- Thread Safety: Thread-safe (
Send + Syncrequired) - Clonable: Cheap cloning via
Arc::clone
§Author
Hu Haixing
Implementations§
Source§impl<T, U, R> ArcBiTransformer<T, U, R>
impl<T, U, R> ArcBiTransformer<T, U, R>
Sourcepub fn new<F>(f: F) -> Self
pub fn new<F>(f: F) -> Self
Creates a new ArcBiTransformer
§Parameters
f- The closure or function to wrap (must be Send + Sync)
§Examples
use prism3_function::{ArcBiTransformer, BiTransformer};
let add = ArcBiTransformer::new(|x: i32, y: i32| x + y);
assert_eq!(add.transform(20, 22), 42);Examples found in repository?
12fn main() {
13 println!("=== BiTransformer Demo ===\n");
14
15 // 1. BoxBiTransformer - Single ownership
16 println!("1. BoxBiTransformer - Single ownership");
17 let add = BoxBiTransformer::new(|x: i32, y: i32| x + y);
18 println!(" add.transform(20, 22) = {}", add.transform(20, 22));
19
20 let multiply = BoxBiTransformer::new(|x: i32, y: i32| x * y);
21 println!(" multiply.transform(6, 7) = {}", multiply.transform(6, 7));
22
23 // Constant bi-transformer
24 let constant = BoxBiTransformer::constant("hello");
25 println!(" constant.transform(1, 2) = {}", constant.transform(1, 2));
26 println!();
27
28 // 2. ArcBiTransformer - Thread-safe, cloneable
29 println!("2. ArcBiTransformer - Thread-safe, cloneable");
30 let arc_add = ArcBiTransformer::new(|x: i32, y: i32| x + y);
31 let arc_add_clone = arc_add.clone();
32
33 println!(
34 " arc_add.transform(10, 15) = {}",
35 arc_add.transform(10, 15)
36 );
37 println!(
38 " arc_add_clone.transform(5, 8) = {}",
39 arc_add_clone.transform(5, 8)
40 );
41 println!();
42
43 // 3. RcBiTransformer - Single-threaded, cloneable
44 println!("3. RcBiTransformer - Single-threaded, cloneable");
45 let rc_multiply = RcBiTransformer::new(|x: i32, y: i32| x * y);
46 let rc_multiply_clone = rc_multiply.clone();
47
48 println!(
49 " rc_multiply.transform(3, 4) = {}",
50 rc_multiply.transform(3, 4)
51 );
52 println!(
53 " rc_multiply_clone.transform(5, 6) = {}",
54 rc_multiply_clone.transform(5, 6)
55 );
56 println!();
57
58 // 4. Conditional BiTransformer
59 println!("4. Conditional BiTransformer");
60 let add_if_positive = BoxBiTransformer::new(|x: i32, y: i32| x + y);
61 let multiply_otherwise = BoxBiTransformer::new(|x: i32, y: i32| x * y);
62 let conditional = add_if_positive
63 .when(|x: &i32, y: &i32| *x > 0 && *y > 0)
64 .or_else(multiply_otherwise);
65
66 println!(
67 " conditional.transform(5, 3) = {} (both positive, add)",
68 conditional.transform(5, 3)
69 );
70 println!(
71 " conditional.transform(-5, 3) = {} (not both positive, multiply)",
72 conditional.transform(-5, 3)
73 );
74 println!();
75
76 // 5. Working with different types
77 println!("5. Working with different types");
78 let format =
79 BoxBiTransformer::new(|name: String, age: i32| format!("{} is {} years old", name, age));
80 println!(
81 " format.transform(\"Alice\", 30) = {}",
82 format.transform("Alice".to_string(), 30)
83 );
84 println!();
85
86 // 6. Closure as BiTransformer
87 println!("6. Closure as BiTransformer");
88 let subtract = |x: i32, y: i32| x - y;
89 println!(
90 " subtract.transform(42, 10) = {}",
91 subtract.transform(42, 10)
92 );
93 println!();
94
95 // 7. Conversion between types
96 println!("7. Conversion between types");
97 let box_add = BoxBiTransformer::new(|x: i32, y: i32| x + y);
98 let rc_add = box_add.into_rc();
99 println!(" Converted BoxBiTransformer to RcBiTransformer");
100 println!(" rc_add.transform(7, 8) = {}", rc_add.transform(7, 8));
101 println!();
102
103 // 8. Safe division with Option
104 println!("8. Safe division with Option");
105 let safe_divide =
106 BoxBiTransformer::new(|x: i32, y: i32| if y == 0 { None } else { Some(x / y) });
107 println!(
108 " safe_divide.transform(42, 2) = {:?}",
109 safe_divide.transform(42, 2)
110 );
111 println!(
112 " safe_divide.transform(42, 0) = {:?}",
113 safe_divide.transform(42, 0)
114 );
115 println!();
116
117 // 9. String concatenation
118 println!("9. String concatenation");
119 let concat = BoxBiTransformer::new(|s1: String, s2: String| format!("{}{}", s1, s2));
120 println!(
121 " concat.transform(\"Hello\", \"World\") = {}",
122 concat.transform("Hello".to_string(), "World".to_string())
123 );
124 println!();
125
126 println!("=== Demo Complete ===");
127}More examples
19fn main() {
20 println!("=== BiTransformer and_then Method Demo ===\n");
21
22 // 1. BoxBiTransformer::and_then - Basic usage
23 println!("1. BoxBiTransformer::and_then - Basic usage");
24 let add = BoxBiTransformer::new(|x: i32, y: i32| x + y);
25 let double = |x: i32| x * 2;
26 let composed = add.and_then(double);
27 println!(" (3 + 5) * 2 = {}", composed.transform(3, 5));
28 println!();
29
30 // 2. BoxBiTransformer::and_then - Chained calls
31 println!("2. BoxBiTransformer::and_then - Chained calls");
32 let multiply = BoxBiTransformer::new(|x: i32, y: i32| x * y);
33 let add_ten = |x: i32| x + 10;
34 let to_string = |x: i32| format!("Result: {}", x);
35 let pipeline = multiply.and_then(add_ten).and_then(to_string);
36 println!(" (6 * 7) + 10 = {}", pipeline.transform(6, 7));
37 println!();
38
39 // 3. ArcBiTransformer::and_then - Shared ownership
40 println!("3. ArcBiTransformer::and_then - Shared ownership");
41 let add_arc = ArcBiTransformer::new(|x: i32, y: i32| x + y);
42 let triple = |x: i32| x * 3;
43 let composed_arc = add_arc.and_then(triple);
44
45 // Original bi-transformer is still available
46 println!(" Original: 20 + 22 = {}", add_arc.transform(20, 22));
47 println!(
48 " Composed: (5 + 3) * 3 = {}",
49 composed_arc.transform(5, 3)
50 );
51 println!();
52
53 // 4. ArcBiTransformer::and_then - Cloneable
54 println!("4. ArcBiTransformer::and_then - Cloneable");
55 let subtract = ArcBiTransformer::new(|x: i32, y: i32| x - y);
56 let abs = |x: i32| x.abs();
57 let composed_abs = subtract.and_then(abs);
58 let cloned = composed_abs.clone();
59
60 println!(
61 " Original: |10 - 15| = {}",
62 composed_abs.transform(10, 15)
63 );
64 println!(" Cloned: |15 - 10| = {}", cloned.transform(15, 10));
65 println!();
66
67 // 5. RcBiTransformer::and_then - Single-threaded sharing
68 println!("5. RcBiTransformer::and_then - Single-threaded sharing");
69 let divide = RcBiTransformer::new(|x: i32, y: i32| x / y);
70 let square = |x: i32| x * x;
71 let composed_rc = divide.and_then(square);
72
73 println!(" Original: 20 / 4 = {}", divide.transform(20, 4));
74 println!(" Composed: (20 / 4)² = {}", composed_rc.transform(20, 4));
75 println!();
76
77 // 6. Type conversion example
78 println!("6. Type conversion example");
79 let concat = BoxBiTransformer::new(|s1: String, s2: String| format!("{} {}", s1, s2));
80 let to_uppercase = |s: String| s.to_uppercase();
81 let get_length = |s: String| s.len();
82
83 let uppercase_pipeline = concat.and_then(to_uppercase);
84 println!(
85 " \"hello\" + \"world\" -> uppercase: {}",
86 uppercase_pipeline.transform("hello".to_string(), "world".to_string())
87 );
88
89 let concat2 = BoxBiTransformer::new(|s1: String, s2: String| format!("{} {}", s1, s2));
90 let length_pipeline = concat2.and_then(get_length);
91 println!(
92 " \"hello\" + \"world\" -> length: {}",
93 length_pipeline.transform("hello".to_string(), "world".to_string())
94 );
95 println!();
96
97 // 7. Real application: Calculator
98 println!("7. Real application: Calculator");
99 let calculate = BoxBiTransformer::new(|a: f64, b: f64| a + b);
100 let round = |x: f64| x.round();
101 let to_int = |x: f64| x as i32;
102
103 let calculator = calculate.and_then(round).and_then(to_int);
104 println!(
105 " 3.7 + 4.8 -> round -> integer: {}",
106 calculator.transform(3.7, 4.8)
107 );
108 println!();
109
110 // 8. Error handling example
111 println!("8. Error handling example");
112 let safe_divide = BoxBiTransformer::new(|x: i32, y: i32| -> Result<i32, String> {
113 if y == 0 {
114 Err("Division by zero is not allowed".to_string())
115 } else {
116 Ok(x / y)
117 }
118 });
119
120 let format_result = |res: Result<i32, String>| match res {
121 Ok(v) => format!("Success: {}", v),
122 Err(e) => format!("Error: {}", e),
123 };
124
125 let safe_calculator = safe_divide.and_then(format_result);
126 println!(" 10 / 2 = {}", safe_calculator.transform(10, 2));
127 println!(" 10 / 0 = {}", safe_calculator.transform(10, 0));
128 println!();
129
130 // 9. Complex data structures
131 println!("9. Complex data structures");
132 #[derive(Debug)]
133 struct Point {
134 x: i32,
135 y: i32,
136 }
137
138 let create_point = BoxBiTransformer::new(|x: i32, y: i32| Point { x, y });
139 let distance_from_origin = |p: Point| ((p.x * p.x + p.y * p.y) as f64).sqrt();
140 let format_distance = |d: f64| format!("{:.2}", d);
141
142 let point_processor = create_point
143 .and_then(distance_from_origin)
144 .and_then(format_distance);
145 println!(
146 " Distance from point(3, 4) to origin: {}",
147 point_processor.transform(3, 4)
148 );
149 println!();
150
151 // 10. Combined usage with when
152 println!("10. Combined usage with when");
153 let add_when = BoxBiTransformer::new(|x: i32, y: i32| x + y);
154 let multiply_when = BoxBiTransformer::new(|x: i32, y: i32| x * y);
155
156 let conditional = add_when
157 .when(|x: &i32, y: &i32| *x > 0 && *y > 0)
158 .or_else(multiply_when);
159
160 let double_result = |x: i32| x * 2;
161 let final_transformer = conditional.and_then(double_result);
162
163 println!(
164 " Add positive numbers then double: (5 + 3) * 2 = {}",
165 final_transformer.transform(5, 3)
166 );
167 println!(
168 " Multiply negative numbers then double: (-5 * 3) * 2 = {}",
169 final_transformer.transform(-5, 3)
170 );
171
172 println!("\n=== Demo completed ===");
173}Sourcepub fn and_then<S, F>(&self, after: F) -> ArcBiTransformer<T, U, S>
pub fn and_then<S, F>(&self, after: F) -> ArcBiTransformer<T, U, S>
Chain composition - applies self first, then after
Creates a new bi-transformer that applies this bi-transformer first, then applies the after transformer to the result. Uses &self, so original bi-transformer remains usable.
§Type Parameters
S- The output type of the after transformerF- The type of the after transformer (must implement Transformer<R, S>)
§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). Must beSend + Sync, can be:- A closure:
|x: R| -> S(must beSend + Sync) - A function pointer:
fn(R) -> S - A
BoxTransformer<R, S> - An
RcTransformer<R, S> - An
ArcTransformer<R, S>(will be moved) - Any type implementing
Transformer<R, S> + Send + Sync
- A closure:
§Returns
A new ArcBiTransformer<T, U, S> representing the composition
§Examples
§Direct value passing (ownership transfer)
use prism3_function::{BiTransformer, ArcBiTransformer, ArcTransformer};
let add = ArcBiTransformer::new(|x: i32, y: i32| x + y);
let double = ArcTransformer::new(|x: i32| x * 2);
// double is moved here
let composed = add.and_then(double);
// Original add bi-transformer still usable (uses &self)
assert_eq!(add.transform(20, 22), 42);
assert_eq!(composed.transform(3, 5), 16); // (3 + 5) * 2
// double.transform(10); // Would not compile - moved§Preserving original with clone
use prism3_function::{BiTransformer, ArcBiTransformer, ArcTransformer};
let add = ArcBiTransformer::new(|x: i32, y: i32| x + y);
let double = ArcTransformer::new(|x: i32| x * 2);
// Clone to preserve original
let composed = add.and_then(double.clone());
assert_eq!(composed.transform(3, 5), 16); // (3 + 5) * 2
// Both originals still usable
assert_eq!(add.transform(20, 22), 42);
assert_eq!(double.transform(10), 20);Examples found in repository?
19fn main() {
20 println!("=== BiTransformer and_then Method Demo ===\n");
21
22 // 1. BoxBiTransformer::and_then - Basic usage
23 println!("1. BoxBiTransformer::and_then - Basic usage");
24 let add = BoxBiTransformer::new(|x: i32, y: i32| x + y);
25 let double = |x: i32| x * 2;
26 let composed = add.and_then(double);
27 println!(" (3 + 5) * 2 = {}", composed.transform(3, 5));
28 println!();
29
30 // 2. BoxBiTransformer::and_then - Chained calls
31 println!("2. BoxBiTransformer::and_then - Chained calls");
32 let multiply = BoxBiTransformer::new(|x: i32, y: i32| x * y);
33 let add_ten = |x: i32| x + 10;
34 let to_string = |x: i32| format!("Result: {}", x);
35 let pipeline = multiply.and_then(add_ten).and_then(to_string);
36 println!(" (6 * 7) + 10 = {}", pipeline.transform(6, 7));
37 println!();
38
39 // 3. ArcBiTransformer::and_then - Shared ownership
40 println!("3. ArcBiTransformer::and_then - Shared ownership");
41 let add_arc = ArcBiTransformer::new(|x: i32, y: i32| x + y);
42 let triple = |x: i32| x * 3;
43 let composed_arc = add_arc.and_then(triple);
44
45 // Original bi-transformer is still available
46 println!(" Original: 20 + 22 = {}", add_arc.transform(20, 22));
47 println!(
48 " Composed: (5 + 3) * 3 = {}",
49 composed_arc.transform(5, 3)
50 );
51 println!();
52
53 // 4. ArcBiTransformer::and_then - Cloneable
54 println!("4. ArcBiTransformer::and_then - Cloneable");
55 let subtract = ArcBiTransformer::new(|x: i32, y: i32| x - y);
56 let abs = |x: i32| x.abs();
57 let composed_abs = subtract.and_then(abs);
58 let cloned = composed_abs.clone();
59
60 println!(
61 " Original: |10 - 15| = {}",
62 composed_abs.transform(10, 15)
63 );
64 println!(" Cloned: |15 - 10| = {}", cloned.transform(15, 10));
65 println!();
66
67 // 5. RcBiTransformer::and_then - Single-threaded sharing
68 println!("5. RcBiTransformer::and_then - Single-threaded sharing");
69 let divide = RcBiTransformer::new(|x: i32, y: i32| x / y);
70 let square = |x: i32| x * x;
71 let composed_rc = divide.and_then(square);
72
73 println!(" Original: 20 / 4 = {}", divide.transform(20, 4));
74 println!(" Composed: (20 / 4)² = {}", composed_rc.transform(20, 4));
75 println!();
76
77 // 6. Type conversion example
78 println!("6. Type conversion example");
79 let concat = BoxBiTransformer::new(|s1: String, s2: String| format!("{} {}", s1, s2));
80 let to_uppercase = |s: String| s.to_uppercase();
81 let get_length = |s: String| s.len();
82
83 let uppercase_pipeline = concat.and_then(to_uppercase);
84 println!(
85 " \"hello\" + \"world\" -> uppercase: {}",
86 uppercase_pipeline.transform("hello".to_string(), "world".to_string())
87 );
88
89 let concat2 = BoxBiTransformer::new(|s1: String, s2: String| format!("{} {}", s1, s2));
90 let length_pipeline = concat2.and_then(get_length);
91 println!(
92 " \"hello\" + \"world\" -> length: {}",
93 length_pipeline.transform("hello".to_string(), "world".to_string())
94 );
95 println!();
96
97 // 7. Real application: Calculator
98 println!("7. Real application: Calculator");
99 let calculate = BoxBiTransformer::new(|a: f64, b: f64| a + b);
100 let round = |x: f64| x.round();
101 let to_int = |x: f64| x as i32;
102
103 let calculator = calculate.and_then(round).and_then(to_int);
104 println!(
105 " 3.7 + 4.8 -> round -> integer: {}",
106 calculator.transform(3.7, 4.8)
107 );
108 println!();
109
110 // 8. Error handling example
111 println!("8. Error handling example");
112 let safe_divide = BoxBiTransformer::new(|x: i32, y: i32| -> Result<i32, String> {
113 if y == 0 {
114 Err("Division by zero is not allowed".to_string())
115 } else {
116 Ok(x / y)
117 }
118 });
119
120 let format_result = |res: Result<i32, String>| match res {
121 Ok(v) => format!("Success: {}", v),
122 Err(e) => format!("Error: {}", e),
123 };
124
125 let safe_calculator = safe_divide.and_then(format_result);
126 println!(" 10 / 2 = {}", safe_calculator.transform(10, 2));
127 println!(" 10 / 0 = {}", safe_calculator.transform(10, 0));
128 println!();
129
130 // 9. Complex data structures
131 println!("9. Complex data structures");
132 #[derive(Debug)]
133 struct Point {
134 x: i32,
135 y: i32,
136 }
137
138 let create_point = BoxBiTransformer::new(|x: i32, y: i32| Point { x, y });
139 let distance_from_origin = |p: Point| ((p.x * p.x + p.y * p.y) as f64).sqrt();
140 let format_distance = |d: f64| format!("{:.2}", d);
141
142 let point_processor = create_point
143 .and_then(distance_from_origin)
144 .and_then(format_distance);
145 println!(
146 " Distance from point(3, 4) to origin: {}",
147 point_processor.transform(3, 4)
148 );
149 println!();
150
151 // 10. Combined usage with when
152 println!("10. Combined usage with when");
153 let add_when = BoxBiTransformer::new(|x: i32, y: i32| x + y);
154 let multiply_when = BoxBiTransformer::new(|x: i32, y: i32| x * y);
155
156 let conditional = add_when
157 .when(|x: &i32, y: &i32| *x > 0 && *y > 0)
158 .or_else(multiply_when);
159
160 let double_result = |x: i32| x * 2;
161 let final_transformer = conditional.and_then(double_result);
162
163 println!(
164 " Add positive numbers then double: (5 + 3) * 2 = {}",
165 final_transformer.transform(5, 3)
166 );
167 println!(
168 " Multiply negative numbers then double: (-5 * 3) * 2 = {}",
169 final_transformer.transform(-5, 3)
170 );
171
172 println!("\n=== Demo completed ===");
173}Sourcepub fn when<P>(self, predicate: P) -> ArcConditionalBiTransformer<T, U, R>
pub fn when<P>(self, predicate: P) -> ArcConditionalBiTransformer<T, U, R>
Creates a conditional bi-transformer (thread-safe version)
Returns a bi-transformer that only executes when a bi-predicate is
satisfied. You must call or_else() to provide an alternative
bi-transformer.
§Parameters
predicate- The condition to check. Note: This parameter is passed by value and will transfer ownership. If you need to preserve the original bi-predicate, clone it first (if it implementsClone). Must beSend + Sync, can be:- A closure:
|x: &T, y: &U| -> bool(requiresSend + Sync) - A function pointer:
fn(&T, &U) -> bool - An
ArcBiPredicate<T, U> - Any type implementing
BiPredicate<T, U> + Send + Sync
- A closure:
§Returns
Returns ArcConditionalBiTransformer<T, U, R>
§Examples
§Basic usage with or_else
use prism3_function::{BiTransformer, ArcBiTransformer};
let add = ArcBiTransformer::new(|x: i32, y: i32| x + y);
let multiply = ArcBiTransformer::new(|x: i32, y: i32| x * y);
let conditional = add.when(|x: &i32, y: &i32| *x > 0 && *y > 0)
.or_else(multiply);
let conditional_clone = conditional.clone();
assert_eq!(conditional.transform(5, 3), 8);
assert_eq!(conditional_clone.transform(-5, 3), -15);§Preserving bi-predicate with clone
use prism3_function::{BiTransformer, ArcBiTransformer, ArcBiPredicate};
let add = ArcBiTransformer::new(|x: i32, y: i32| x + y);
let both_positive = ArcBiPredicate::new(|x: &i32, y: &i32|
*x > 0 && *y > 0);
// Clone to preserve original bi-predicate
let conditional = add.when(both_positive.clone())
.or_else(ArcBiTransformer::new(|x, y| x * y));
assert_eq!(conditional.transform(5, 3), 8);
// Original bi-predicate still usable
assert!(both_positive.test(&5, &3));