prism3_function/bi_transformer_once.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2025.
4 * 3-Prism Co. Ltd.
5 *
6 * All rights reserved.
7 *
8 ******************************************************************************/
9//! # BiTransformerOnce Types
10//!
11//! Provides Rust implementations of consuming bi-transformer traits similar to
12//! Rust's `FnOnce` trait, but with value-oriented semantics for functional
13//! programming patterns with two inputs.
14//!
15//! This module provides the `BiTransformerOnce<T, U, R>` trait and one-time use
16//! implementations:
17//!
18//! - [`BoxBiTransformerOnce`]: Single ownership, one-time use
19//!
20//! # Author
21//!
22//! Hu Haixing
23
24use crate::bi_predicate::{BiPredicate, BoxBiPredicate};
25
26// ============================================================================
27// Core Trait
28// ============================================================================
29
30/// BiTransformerOnce trait - consuming bi-transformation that takes ownership
31///
32/// Defines the behavior of a consuming bi-transformer: converting two values of
33/// types `T` and `U` to a value of type `R` by taking ownership of self and
34/// both inputs. This trait is analogous to `FnOnce(T, U) -> R`.
35///
36/// # Type Parameters
37///
38/// * `T` - The type of the first input value (consumed)
39/// * `U` - The type of the second input value (consumed)
40/// * `R` - The type of the output value
41///
42/// # Author
43///
44/// Hu Haixing
45pub trait BiTransformerOnce<T, U, R> {
46 /// Transforms two input values, consuming self and both inputs
47 ///
48 /// # Parameters
49 ///
50 /// * `first` - The first input value (consumed)
51 /// * `second` - The second input value (consumed)
52 ///
53 /// # Returns
54 ///
55 /// The transformed output value
56 fn transform(self, first: T, second: U) -> R;
57
58 /// Converts to BoxBiTransformerOnce
59 ///
60 /// **⚠️ Consumes `self`**: The original bi-transformer becomes unavailable
61 /// after calling this method.
62 ///
63 /// # Returns
64 ///
65 /// Returns `BoxBiTransformerOnce<T, U, R>`
66 fn into_box(self) -> BoxBiTransformerOnce<T, U, R>
67 where
68 Self: Sized + 'static,
69 T: 'static,
70 U: 'static,
71 R: 'static;
72
73 /// Converts bi-transformer to a closure
74 ///
75 /// **⚠️ Consumes `self`**: The original bi-transformer becomes unavailable
76 /// after calling this method.
77 ///
78 /// # Returns
79 ///
80 /// Returns a closure that implements `FnOnce(T, U) -> R`
81 fn into_fn(self) -> impl FnOnce(T, U) -> R
82 where
83 Self: Sized + 'static,
84 T: 'static,
85 U: 'static,
86 R: 'static;
87}
88
89// ============================================================================
90// BoxBiTransformerOnce - Box<dyn FnOnce(T, U) -> R>
91// ============================================================================
92
93/// BoxBiTransformerOnce - consuming bi-transformer wrapper based on
94/// `Box<dyn FnOnce>`
95///
96/// A bi-transformer wrapper that provides single ownership with one-time use
97/// semantics. Consumes self and both input values.
98///
99/// # Features
100///
101/// - **Based on**: `Box<dyn FnOnce(T, U) -> R>`
102/// - **Ownership**: Single ownership, cannot be cloned
103/// - **Reusability**: Can only be called once (consumes self and inputs)
104/// - **Thread Safety**: Not thread-safe (no `Send + Sync` requirement)
105///
106/// # Author
107///
108/// Hu Haixing
109pub struct BoxBiTransformerOnce<T, U, R> {
110 function: Box<dyn FnOnce(T, U) -> R>,
111}
112
113impl<T, U, R> BoxBiTransformerOnce<T, U, R>
114where
115 T: 'static,
116 U: 'static,
117 R: 'static,
118{
119 /// Creates a new BoxBiTransformerOnce
120 ///
121 /// # Parameters
122 ///
123 /// * `f` - The closure or function to wrap
124 ///
125 /// # Examples
126 ///
127 /// ```rust
128 /// use prism3_function::{BoxBiTransformerOnce, BiTransformerOnce};
129 ///
130 /// let add = BoxBiTransformerOnce::new(|x: i32, y: i32| x + y);
131 /// assert_eq!(add.transform(20, 22), 42);
132 /// ```
133 pub fn new<F>(f: F) -> Self
134 where
135 F: FnOnce(T, U) -> R + 'static,
136 {
137 BoxBiTransformerOnce {
138 function: Box::new(f),
139 }
140 }
141
142 /// Chain composition - applies self first, then after
143 ///
144 /// Creates a new bi-transformer that applies this bi-transformer first,
145 /// then applies the after transformer to the result. Consumes self and
146 /// returns a new `BoxBiTransformerOnce`.
147 ///
148 /// # Type Parameters
149 ///
150 /// * `S` - The output type of the after transformer
151 /// * `F` - The type of the after transformer (must implement TransformerOnce<R, S>)
152 ///
153 /// # Parameters
154 ///
155 /// * `after` - The transformer to apply after self. **Note: This parameter
156 /// is passed by value and will transfer ownership.** Since
157 /// `BoxBiTransformerOnce` cannot be cloned, the parameter will be consumed.
158 /// Can be:
159 /// - A closure: `|x: R| -> S`
160 /// - A function pointer: `fn(R) -> S`
161 /// - A `BoxTransformerOnce<R, S>`
162 /// - Any type implementing `TransformerOnce<R, S>`
163 ///
164 /// # Returns
165 ///
166 /// A new `BoxBiTransformerOnce<T, U, S>` representing the composition
167 ///
168 /// # Examples
169 ///
170 /// ```rust
171 /// use prism3_function::{BiTransformerOnce, BoxBiTransformerOnce};
172 ///
173 /// let add = BoxBiTransformerOnce::new(|x: i32, y: i32| x + y);
174 /// let double = |x: i32| x * 2;
175 ///
176 /// // Both add and double are moved and consumed
177 /// let composed = add.and_then(double);
178 /// assert_eq!(composed.transform(3, 5), 16); // (3 + 5) * 2
179 /// // add.transform(1, 2); // Would not compile - moved
180 /// // double(10); // Would not compile - moved
181 /// ```
182 pub fn and_then<S, F>(self, after: F) -> BoxBiTransformerOnce<T, U, S>
183 where
184 S: 'static,
185 F: crate::transformer_once::TransformerOnce<R, S> + 'static,
186 {
187 let self_fn = self.function;
188 BoxBiTransformerOnce::new(move |t: T, u: U| after.transform(self_fn(t, u)))
189 }
190
191 /// Creates a conditional bi-transformer
192 ///
193 /// Returns a bi-transformer that only executes when a bi-predicate is
194 /// satisfied. You must call `or_else()` to provide an alternative
195 /// bi-transformer.
196 ///
197 /// # Parameters
198 ///
199 /// * `predicate` - The condition to check. **Note: This parameter is passed
200 /// by value and will transfer ownership.** If you need to preserve the
201 /// original bi-predicate, clone it first (if it implements `Clone`).
202 /// Can be:
203 /// - A closure: `|x: &T, y: &U| -> bool`
204 /// - A function pointer: `fn(&T, &U) -> bool`
205 /// - A `BoxBiPredicate<T, U>`
206 /// - An `RcBiPredicate<T, U>`
207 /// - An `ArcBiPredicate<T, U>`
208 /// - Any type implementing `BiPredicate<T, U>`
209 ///
210 /// # Returns
211 ///
212 /// Returns `BoxConditionalBiTransformerOnce<T, U, R>`
213 ///
214 /// # Examples
215 ///
216 /// ## Basic usage with or_else
217 ///
218 /// ```rust
219 /// use prism3_function::{BiTransformerOnce, BoxBiTransformerOnce};
220 ///
221 /// let add = BoxBiTransformerOnce::new(|x: i32, y: i32| x + y);
222 /// let multiply = BoxBiTransformerOnce::new(|x: i32, y: i32| x * y);
223 /// let conditional = add.when(|x: &i32, y: &i32| *x > 0 && *y > 0)
224 /// .or_else(multiply);
225 /// assert_eq!(conditional.transform(5, 3), 8);
226 ///
227 /// let add2 = BoxBiTransformerOnce::new(|x: i32, y: i32| x + y);
228 /// let multiply2 = BoxBiTransformerOnce::new(|x: i32, y: i32| x * y);
229 /// let conditional2 = add2.when(|x: &i32, y: &i32| *x > 0 && *y > 0)
230 /// .or_else(multiply2);
231 /// assert_eq!(conditional2.transform(-5, 3), -15);
232 /// ```
233 ///
234 /// ## Preserving bi-predicate with clone
235 ///
236 /// ```rust
237 /// use prism3_function::{BiTransformerOnce, BoxBiTransformerOnce, RcBiPredicate};
238 ///
239 /// let add = BoxBiTransformerOnce::new(|x: i32, y: i32| x + y);
240 /// let both_positive = RcBiPredicate::new(|x: &i32, y: &i32|
241 /// *x > 0 && *y > 0);
242 ///
243 /// // Clone to preserve original bi-predicate
244 /// let conditional = add.when(both_positive.clone())
245 /// .or_else(BoxBiTransformerOnce::new(|x, y| x * y));
246 ///
247 /// assert_eq!(conditional.transform(5, 3), 8);
248 ///
249 /// // Original bi-predicate still usable
250 /// assert!(both_positive.test(&5, &3));
251 /// ```
252 pub fn when<P>(self, predicate: P) -> BoxConditionalBiTransformerOnce<T, U, R>
253 where
254 P: BiPredicate<T, U> + 'static,
255 {
256 BoxConditionalBiTransformerOnce {
257 transformer: self,
258 predicate: predicate.into_box(),
259 }
260 }
261}
262
263impl<T, U, R> BoxBiTransformerOnce<T, U, R>
264where
265 T: 'static,
266 U: 'static,
267 R: Clone + 'static,
268{
269 /// Creates a constant bi-transformer
270 ///
271 /// # Examples
272 ///
273 /// ```rust
274 /// use prism3_function::{BoxBiTransformerOnce, BiTransformerOnce};
275 ///
276 /// let constant = BoxBiTransformerOnce::constant("hello");
277 /// assert_eq!(constant.transform(123, 456), "hello");
278 /// ```
279 pub fn constant(value: R) -> BoxBiTransformerOnce<T, U, R> {
280 BoxBiTransformerOnce::new(move |_, _| value.clone())
281 }
282}
283
284impl<T, U, R> BiTransformerOnce<T, U, R> for BoxBiTransformerOnce<T, U, R> {
285 fn transform(self, first: T, second: U) -> R {
286 (self.function)(first, second)
287 }
288
289 fn into_box(self) -> BoxBiTransformerOnce<T, U, R>
290 where
291 T: 'static,
292 U: 'static,
293 R: 'static,
294 {
295 // Zero-cost: directly return itself
296 self
297 }
298
299 fn into_fn(self) -> impl FnOnce(T, U) -> R
300 where
301 T: 'static,
302 U: 'static,
303 R: 'static,
304 {
305 move |t: T, u: U| self.transform(t, u)
306 }
307}
308
309// ============================================================================
310// BoxConditionalBiTransformerOnce - Box-based Conditional BiTransformer
311// ============================================================================
312
313/// BoxConditionalBiTransformerOnce struct
314///
315/// A conditional consuming bi-transformer that only executes when a bi-predicate
316/// is satisfied. Uses `BoxBiTransformerOnce` and `BoxBiPredicate` for single
317/// ownership semantics.
318///
319/// This type is typically created by calling `BoxBiTransformerOnce::when()` and
320/// is designed to work with the `or_else()` method to create if-then-else logic.
321///
322/// # Features
323///
324/// - **Single Ownership**: Not cloneable, consumes `self` on use
325/// - **One-time Use**: Can only be called once
326/// - **Conditional Execution**: Only transforms when bi-predicate returns `true`
327/// - **Chainable**: Can add `or_else` branch to create if-then-else logic
328///
329/// # Examples
330///
331/// ## With or_else Branch
332///
333/// ```rust
334/// use prism3_function::{BiTransformerOnce, BoxBiTransformerOnce};
335///
336/// let add = BoxBiTransformerOnce::new(|x: i32, y: i32| x + y);
337/// let multiply = BoxBiTransformerOnce::new(|x: i32, y: i32| x * y);
338/// let conditional = add.when(|x: &i32, y: &i32| *x > 0 && *y > 0).or_else(multiply);
339/// assert_eq!(conditional.transform(5, 3), 8); // when branch executed
340///
341/// let add2 = BoxBiTransformerOnce::new(|x: i32, y: i32| x + y);
342/// let multiply2 = BoxBiTransformerOnce::new(|x: i32, y: i32| x * y);
343/// let conditional2 = add2.when(|x: &i32, y: &i32| *x > 0 && *y > 0).or_else(multiply2);
344/// assert_eq!(conditional2.transform(-5, 3), -15); // or_else branch executed
345/// ```
346///
347/// # Author
348///
349/// Haixing Hu
350pub struct BoxConditionalBiTransformerOnce<T, U, R> {
351 transformer: BoxBiTransformerOnce<T, U, R>,
352 predicate: BoxBiPredicate<T, U>,
353}
354
355impl<T, U, R> BoxConditionalBiTransformerOnce<T, U, R>
356where
357 T: 'static,
358 U: 'static,
359 R: 'static,
360{
361 /// Adds an else branch
362 ///
363 /// Executes the original bi-transformer when the condition is satisfied,
364 /// otherwise executes else_transformer.
365 ///
366 /// # Parameters
367 ///
368 /// * `else_transformer` - The bi-transformer for the else branch, can be:
369 /// - Closure: `|x: T, y: U| -> R`
370 /// - `BoxBiTransformerOnce<T, U, R>`
371 /// - Any type implementing `BiTransformerOnce<T, U, R>`
372 ///
373 /// # Returns
374 ///
375 /// Returns the composed `BoxBiTransformerOnce<T, U, R>`
376 ///
377 /// # Examples
378 ///
379 /// ## Using a closure (recommended)
380 ///
381 /// ```rust
382 /// use prism3_function::{BiTransformerOnce, BoxBiTransformerOnce};
383 ///
384 /// let add = BoxBiTransformerOnce::new(|x: i32, y: i32| x + y);
385 /// let conditional = add.when(|x: &i32, y: &i32| *x > 0 && *y > 0).or_else(|x: i32, y: i32| x * y);
386 /// assert_eq!(conditional.transform(5, 3), 8); // Condition satisfied, execute add
387 ///
388 /// let add2 = BoxBiTransformerOnce::new(|x: i32, y: i32| x + y);
389 /// let conditional2 = add2.when(|x: &i32, y: &i32| *x > 0 && *y > 0).or_else(|x: i32, y: i32| x * y);
390 /// assert_eq!(conditional2.transform(-5, 3), -15); // Condition not satisfied, execute multiply
391 /// ```
392 pub fn or_else<F>(self, else_transformer: F) -> BoxBiTransformerOnce<T, U, R>
393 where
394 F: BiTransformerOnce<T, U, R> + 'static,
395 {
396 let pred = self.predicate;
397 let then_trans = self.transformer;
398 BoxBiTransformerOnce::new(move |t, u| {
399 if pred.test(&t, &u) {
400 then_trans.transform(t, u)
401 } else {
402 else_transformer.transform(t, u)
403 }
404 })
405 }
406}
407
408// ============================================================================
409// Blanket implementation for standard FnOnce trait
410// ============================================================================
411
412/// Implement BiTransformerOnce<T, U, R> for any type that implements
413/// FnOnce(T, U) -> R
414///
415/// This allows once-callable closures and function pointers to be used
416/// directly with our BiTransformerOnce trait without wrapping.
417///
418/// # Examples
419///
420/// ```rust
421/// use prism3_function::BiTransformerOnce;
422///
423/// fn add(x: i32, y: i32) -> i32 {
424/// x + y
425/// }
426///
427/// assert_eq!(add.transform(20, 22), 42);
428///
429/// let owned_x = String::from("hello");
430/// let owned_y = String::from("world");
431/// let concat = |x: String, y: String| {
432/// format!("{} {}", x, y)
433/// };
434/// assert_eq!(concat.transform(owned_x, owned_y), "hello world");
435/// ```
436///
437/// # Author
438///
439/// Hu Haixing
440impl<F, T, U, R> BiTransformerOnce<T, U, R> for F
441where
442 F: FnOnce(T, U) -> R,
443 T: 'static,
444 U: 'static,
445 R: 'static,
446{
447 fn transform(self, first: T, second: U) -> R {
448 self(first, second)
449 }
450
451 fn into_box(self) -> BoxBiTransformerOnce<T, U, R>
452 where
453 Self: Sized + 'static,
454 {
455 BoxBiTransformerOnce::new(self)
456 }
457
458 fn into_fn(self) -> impl FnOnce(T, U) -> R
459 where
460 Self: Sized + 'static,
461 {
462 move |first: T, second: U| -> R { self(first, second) }
463 }
464}
465
466// ============================================================================
467// FnBiTransformerOnceOps - Extension trait for FnOnce(T, U) -> R bi-transformers
468// ============================================================================
469
470/// Extension trait for closures implementing `FnOnce(T, U) -> R`
471///
472/// Provides composition methods (`and_then`, `when`) for one-time use
473/// bi-transformer closures and function pointers without requiring explicit
474/// wrapping in `BoxBiTransformerOnce`.
475///
476/// This trait is automatically implemented for all closures and function
477/// pointers that implement `FnOnce(T, U) -> R`.
478///
479/// # Design Rationale
480///
481/// While closures automatically implement `BiTransformerOnce<T, U, R>` through
482/// blanket implementation, they don't have access to instance methods like
483/// `and_then` and `when`. This extension trait provides those methods,
484/// returning `BoxBiTransformerOnce` for maximum flexibility.
485///
486/// # Examples
487///
488/// ## Chain composition with and_then
489///
490/// ```rust
491/// use prism3_function::{BiTransformerOnce, FnBiTransformerOnceOps};
492///
493/// let add = |x: i32, y: i32| x + y;
494/// let double = |x: i32| x * 2;
495///
496/// let composed = add.and_then(double);
497/// assert_eq!(composed.transform(3, 5), 16); // (3 + 5) * 2
498/// ```
499///
500/// ## Conditional execution with when
501///
502/// ```rust
503/// use prism3_function::{BiTransformerOnce, FnBiTransformerOnceOps};
504///
505/// let add = |x: i32, y: i32| x + y;
506/// let multiply = |x: i32, y: i32| x * y;
507///
508/// let conditional = add.when(|x: &i32, y: &i32| *x > 0 && *y > 0).or_else(multiply);
509/// assert_eq!(conditional.transform(5, 3), 8); // add
510/// ```
511///
512/// # Author
513///
514/// Hu Haixing
515pub trait FnBiTransformerOnceOps<T, U, R>: FnOnce(T, U) -> R + Sized + 'static {
516 /// Chain composition - applies self first, then after
517 ///
518 /// Creates a new bi-transformer that applies this bi-transformer first,
519 /// then applies the after transformer to the result. Consumes self and
520 /// returns a `BoxBiTransformerOnce`.
521 ///
522 /// # Type Parameters
523 ///
524 /// * `S` - The output type of the after transformer
525 /// * `F` - The type of the after transformer (must implement TransformerOnce<R, S>)
526 ///
527 /// # Parameters
528 ///
529 /// * `after` - The transformer to apply after self. **Note: This parameter
530 /// is passed by value and will transfer ownership.** Since this is a
531 /// `FnOnce` bi-transformer, the parameter will be consumed. Can be:
532 /// - A closure: `|x: R| -> S`
533 /// - A function pointer: `fn(R) -> S`
534 /// - A `BoxTransformerOnce<R, S>`
535 /// - Any type implementing `TransformerOnce<R, S>`
536 ///
537 /// # Returns
538 ///
539 /// A new `BoxBiTransformerOnce<T, U, S>` representing the composition
540 ///
541 /// # Examples
542 ///
543 /// ```rust
544 /// use prism3_function::{BiTransformerOnce, FnBiTransformerOnceOps,
545 /// BoxTransformerOnce};
546 ///
547 /// let add = |x: i32, y: i32| x + y;
548 /// let to_string = BoxTransformerOnce::new(|x: i32| x.to_string());
549 ///
550 /// // to_string is moved and consumed
551 /// let composed = add.and_then(to_string);
552 /// assert_eq!(composed.transform(20, 22), "42");
553 /// // to_string.transform(10); // Would not compile - moved
554 /// ```
555 fn and_then<S, F>(self, after: F) -> BoxBiTransformerOnce<T, U, S>
556 where
557 S: 'static,
558 F: crate::transformer_once::TransformerOnce<R, S> + 'static,
559 T: 'static,
560 U: 'static,
561 R: 'static,
562 {
563 BoxBiTransformerOnce::new(move |t: T, u: U| after.transform(self(t, u)))
564 }
565
566 /// Creates a conditional bi-transformer
567 ///
568 /// Returns a bi-transformer that only executes when a bi-predicate is
569 /// satisfied. You must call `or_else()` to provide an alternative
570 /// bi-transformer for when the condition is not satisfied.
571 ///
572 /// # Parameters
573 ///
574 /// * `predicate` - The condition to check. **Note: This parameter is passed
575 /// by value and will transfer ownership.** If you need to preserve the
576 /// original bi-predicate, clone it first (if it implements `Clone`).
577 /// Can be:
578 /// - A closure: `|x: &T, y: &U| -> bool`
579 /// - A function pointer: `fn(&T, &U) -> bool`
580 /// - A `BoxBiPredicate<T, U>`
581 /// - An `RcBiPredicate<T, U>`
582 /// - An `ArcBiPredicate<T, U>`
583 /// - Any type implementing `BiPredicate<T, U>`
584 ///
585 /// # Returns
586 ///
587 /// Returns `BoxConditionalBiTransformerOnce<T, U, R>`
588 ///
589 /// # Examples
590 ///
591 /// ## Basic usage with or_else
592 ///
593 /// ```rust
594 /// use prism3_function::{BiTransformerOnce, FnBiTransformerOnceOps};
595 ///
596 /// let add = |x: i32, y: i32| x + y;
597 /// let multiply = |x: i32, y: i32| x * y;
598 /// let conditional = add.when(|x: &i32, y: &i32| *x > 0)
599 /// .or_else(multiply);
600 ///
601 /// assert_eq!(conditional.transform(5, 3), 8);
602 /// ```
603 ///
604 /// ## Preserving bi-predicate with clone
605 ///
606 /// ```rust
607 /// use prism3_function::{BiTransformerOnce, FnBiTransformerOnceOps,
608 /// RcBiPredicate};
609 ///
610 /// let add = |x: i32, y: i32| x + y;
611 /// let both_positive = RcBiPredicate::new(|x: &i32, y: &i32|
612 /// *x > 0 && *y > 0);
613 ///
614 /// // Clone to preserve original bi-predicate
615 /// let conditional = add.when(both_positive.clone())
616 /// .or_else(|x: i32, y: i32| x * y);
617 ///
618 /// assert_eq!(conditional.transform(5, 3), 8);
619 ///
620 /// // Original bi-predicate still usable
621 /// assert!(both_positive.test(&5, &3));
622 /// ```
623 fn when<P>(self, predicate: P) -> BoxConditionalBiTransformerOnce<T, U, R>
624 where
625 P: BiPredicate<T, U> + 'static,
626 T: 'static,
627 U: 'static,
628 R: 'static,
629 {
630 BoxBiTransformerOnce::new(self).when(predicate)
631 }
632}
633
634/// Blanket implementation of FnBiTransformerOnceOps for all closures
635///
636/// Automatically implements `FnBiTransformerOnceOps<T, U, R>` for any type that
637/// implements `FnOnce(T, U) -> R`.
638///
639/// # Author
640///
641/// Hu Haixing
642impl<T, U, R, F> FnBiTransformerOnceOps<T, U, R> for F where F: FnOnce(T, U) -> R + 'static {}
643
644// ============================================================================
645// BinaryOperatorOnce Trait - Marker trait for BiTransformerOnce<T, T, T>
646// ============================================================================
647
648/// BinaryOperatorOnce trait - marker trait for one-time use binary operators
649///
650/// A one-time use binary operator takes two values of type `T` and produces a
651/// value of the same type `T`, consuming self in the process. This trait
652/// extends `BiTransformerOnce<T, T, T>` to provide semantic clarity for
653/// same-type binary operations with consuming semantics. Equivalent to Java's
654/// `BinaryOperator<T>` but with FnOnce semantics.
655///
656/// # Automatic Implementation
657///
658/// This trait is automatically implemented for all types that implement
659/// `BiTransformerOnce<T, T, T>`, so you don't need to implement it manually.
660///
661/// # Type Parameters
662///
663/// * `T` - The type of both input values and the output value
664///
665/// # Examples
666///
667/// ## Using in generic constraints
668///
669/// ```rust
670/// use prism3_function::{BinaryOperatorOnce, BiTransformerOnce};
671///
672/// fn combine<T, O>(a: T, b: T, op: O) -> T
673/// where
674/// O: BinaryOperatorOnce<T>,
675/// {
676/// op.transform(a, b)
677/// }
678///
679/// let multiply = |x: i32, y: i32| x * y;
680/// assert_eq!(combine(6, 7, multiply), 42);
681/// ```
682///
683/// # Author
684///
685/// Hu Haixing
686pub trait BinaryOperatorOnce<T>: BiTransformerOnce<T, T, T> {}
687
688/// Blanket implementation of BinaryOperatorOnce for all BiTransformerOnce<T, T, T>
689///
690/// This automatically implements `BinaryOperatorOnce<T>` for any type that
691/// implements `BiTransformerOnce<T, T, T>`.
692///
693/// # Author
694///
695/// Hu Haixing
696impl<F, T> BinaryOperatorOnce<T> for F
697where
698 F: BiTransformerOnce<T, T, T>,
699 T: 'static,
700{
701 // empty
702}
703
704// ============================================================================
705// Type Aliases for BinaryOperatorOnce (BiTransformerOnce<T, T, T>)
706// ============================================================================
707
708/// Type alias for `BoxBiTransformerOnce<T, T, T>`
709///
710/// Represents a one-time use binary operator that takes two values of type `T`
711/// and produces a value of the same type `T`. Equivalent to Java's
712/// `BinaryOperator<T>` with consuming semantics (FnOnce).
713///
714/// # Examples
715///
716/// ```rust
717/// use prism3_function::{BoxBinaryOperatorOnce, BiTransformerOnce};
718///
719/// let add: BoxBinaryOperatorOnce<i32> = BoxBinaryOperatorOnce::new(|x, y| x + y);
720/// assert_eq!(add.transform(20, 22), 42);
721/// ```
722///
723/// # Author
724///
725/// Hu Haixing
726pub type BoxBinaryOperatorOnce<T> = BoxBiTransformerOnce<T, T, T>;