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>;