Skip to main content

qubit_function/functions/
function.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026.
4 *    Haixing Hu, Qubit Co. Ltd.
5 *
6 *    All rights reserved.
7 *
8 ******************************************************************************/
9//! # Function Types
10//!
11//! Provides Rust implementations of function traits for computing output values
12//! from input references. Functions borrow input values (not consuming them)
13//! and produce output values.
14//!
15//! It is similar to the `Fn(&T) -> R` trait in the standard library.
16//!
17//! This module provides the `Function<T, R>` trait and three
18//! implementations:
19//!
20//! - [`BoxFunction`]: Single ownership, not cloneable
21//! - [`ArcFunction`]: Thread-safe shared ownership, cloneable
22//! - [`RcFunction`]: Single-threaded shared ownership, cloneable
23//!
24//! # Author
25//!
26//! Haixing Hu
27use std::rc::Rc;
28use std::sync::Arc;
29
30use crate::functions::{
31    function_once::BoxFunctionOnce,
32    macros::{
33        impl_box_conditional_function,
34        impl_box_function_methods,
35        impl_conditional_function_clone,
36        impl_conditional_function_debug_display,
37        impl_fn_ops_trait,
38        impl_function_clone,
39        impl_function_common_methods,
40        impl_function_constant_method,
41        impl_function_debug_display,
42        impl_function_identity_method,
43        impl_shared_conditional_function,
44        impl_shared_function_methods,
45    },
46};
47use crate::macros::{
48    impl_arc_conversions,
49    impl_box_conversions,
50    impl_closure_trait,
51    impl_rc_conversions,
52};
53use crate::predicates::predicate::{
54    ArcPredicate,
55    BoxPredicate,
56    Predicate,
57    RcPredicate,
58};
59
60// ============================================================================
61// Core Trait
62// ============================================================================
63
64/// Function trait - computes output from input reference
65///
66/// Defines the behavior of a function: computing a value of type `R`
67/// from a reference to type `T` without consuming the input. This is analogous to
68/// `Fn(&T) -> R` in Rust's standard library, similar to Java's `Function<T, R>`.
69///
70/// # Type Parameters
71///
72/// * `T` - The type of the input value (borrowed)
73/// * `R` - The type of the output value
74///
75/// # Author
76///
77/// Haixing Hu
78pub trait Function<T, R> {
79    /// Applies the function to the input reference to produce an output value
80    ///
81    /// # Parameters
82    ///
83    /// * `t` - Reference to the input value
84    ///
85    /// # Returns
86    ///
87    /// The computed output value
88    fn apply(&self, t: &T) -> R;
89
90    /// Converts to BoxFunction
91    ///
92    /// **⚠️ Consumes `self`**: The original function becomes
93    /// unavailable after calling this method.
94    ///
95    /// # Default Implementation
96    ///
97    /// The default implementation wraps `self` in a `Box` and creates a
98    /// `BoxFunction`. Types can override this method to provide more
99    /// efficient conversions.
100    ///
101    /// # Returns
102    ///
103    /// Returns `BoxFunction<T, R>`
104    fn into_box(self) -> BoxFunction<T, R>
105    where
106        Self: Sized + 'static,
107        T: 'static,
108        R: 'static,
109    {
110        BoxFunction::new(move |t| self.apply(t))
111    }
112
113    /// Converts to RcFunction
114    ///
115    /// **⚠️ Consumes `self`**: The original function becomes
116    /// unavailable after calling this method.
117    ///
118    /// # Default Implementation
119    ///
120    /// The default implementation wraps `self` in an `Rc` and creates an
121    /// `RcFunction`. Types can override this method to provide more
122    /// efficient conversions.
123    ///
124    /// # Returns
125    ///
126    /// Returns `RcFunction<T, R>`
127    fn into_rc(self) -> RcFunction<T, R>
128    where
129        Self: Sized + 'static,
130        T: 'static,
131        R: 'static,
132    {
133        RcFunction::new(move |t| self.apply(t))
134    }
135
136    /// Converts to ArcFunction
137    ///
138    /// **⚠️ Consumes `self`**: The original function becomes
139    /// unavailable after calling this method.
140    ///
141    /// # Default Implementation
142    ///
143    /// The default implementation wraps `self` in an `Arc` and creates
144    /// an `ArcFunction`. Types can override this method to provide
145    /// more efficient conversions.
146    ///
147    /// # Returns
148    ///
149    /// Returns `ArcFunction<T, R>`
150    fn into_arc(self) -> ArcFunction<T, R>
151    where
152        Self: Sized + Send + Sync + 'static,
153        T: Send + Sync + 'static,
154        R: 'static,
155    {
156        ArcFunction::new(move |t| self.apply(t))
157    }
158
159    /// Converts function to a closure
160    ///
161    /// **⚠️ Consumes `self`**: The original function becomes
162    /// unavailable after calling this method.
163    ///
164    /// # Default Implementation
165    ///
166    /// The default implementation creates a closure that captures `self`
167    /// and calls its `transform` method. Types can override this method
168    /// to provide more efficient conversions.
169    ///
170    /// # Returns
171    ///
172    /// Returns a closure that implements `Fn(&T) -> R`
173    fn into_fn(self) -> impl Fn(&T) -> R
174    where
175        Self: Sized + 'static,
176    {
177        move |t| self.apply(t)
178    }
179
180    /// Converts to FunctionOnce
181    ///
182    /// **⚠️ Consumes `self`**: The original function becomes unavailable after calling this method.
183    ///
184    /// Converts a reusable function to a one-time function that consumes itself on use.
185    /// This enables passing `Function` to functions that require `FunctionOnce`.
186    ///
187    /// # Returns
188    ///
189    /// Returns a `BoxFunctionOnce<T, R>`
190    ///
191    /// # Examples
192    ///
193    /// ```rust
194    ///
195    /// fn takes_once<F: FunctionOnce<i32, i32>>(func: F, value: &i32) -> i32 {
196    ///     func.apply(value)
197    /// }
198    ///
199    /// let func = BoxFunction::new(|x: &i32| x * 2);
200    /// let result = takes_once(func.into_once(), &5);
201    /// assert_eq!(result, 10);
202    /// ```
203    fn into_once(self) -> BoxFunctionOnce<T, R>
204    where
205        Self: Sized + 'static,
206        T: 'static,
207        R: 'static,
208    {
209        BoxFunctionOnce::new(move |t| self.apply(t))
210    }
211
212    /// Converts to BoxFunction without consuming self
213    ///
214    /// **📌 Borrows `&self`**: The original function remains usable
215    /// after calling this method.
216    ///
217    /// # Default Implementation
218    ///
219    /// The default implementation creates a new `BoxFunction` that
220    /// captures a reference-counted clone. Types implementing `Clone`
221    /// can override this method to provide more efficient conversions.
222    ///
223    /// # Returns
224    ///
225    /// Returns `BoxFunction<T, R>`
226    ///
227    /// # Examples
228    ///
229    /// ```rust
230    /// use qubit_function::{ArcFunction, Function};
231    ///
232    /// let double = ArcFunction::new(|x: i32| x * 2);
233    /// let boxed = double.to_box();
234    ///
235    /// // Original function still usable
236    /// assert_eq!(double.apply(21), 42);
237    /// assert_eq!(boxed.apply(21), 42);
238    /// ```
239    fn to_box(&self) -> BoxFunction<T, R>
240    where
241        Self: Clone + 'static,
242        T: 'static,
243        R: 'static,
244    {
245        self.clone().into_box()
246    }
247
248    /// Converts to RcFunction without consuming self
249    ///
250    /// **📌 Borrows `&self`**: The original function remains usable
251    /// after calling this method.
252    ///
253    /// # Default Implementation
254    ///
255    /// The default implementation creates a new `RcFunction` that
256    /// captures a reference-counted clone. Types implementing `Clone`
257    /// can override this method to provide more efficient conversions.
258    ///
259    /// # Returns
260    ///
261    /// Returns `RcFunction<T, R>`
262    ///
263    /// # Examples
264    ///
265    /// ```rust
266    /// use qubit_function::{ArcFunction, Function};
267    ///
268    /// let double = ArcFunction::new(|x: i32| x * 2);
269    /// let rc = double.to_rc();
270    ///
271    /// // Original function still usable
272    /// assert_eq!(double.apply(21), 42);
273    /// assert_eq!(rc.apply(21), 42);
274    /// ```
275    fn to_rc(&self) -> RcFunction<T, R>
276    where
277        Self: Clone + 'static,
278        T: 'static,
279        R: 'static,
280    {
281        self.clone().into_rc()
282    }
283
284    /// Converts to ArcFunction without consuming self
285    ///
286    /// **📌 Borrows `&self`**: The original function remains usable
287    /// after calling this method.
288    ///
289    /// # Default Implementation
290    ///
291    /// The default implementation creates a new `ArcFunction` that
292    /// captures a reference-counted clone. Types implementing `Clone`
293    /// can override this method to provide more efficient conversions.
294    ///
295    /// # Returns
296    ///
297    /// Returns `ArcFunction<T, R>`
298    ///
299    /// # Examples
300    ///
301    /// ```rust
302    /// use qubit_function::{ArcFunction, Function};
303    ///
304    /// let double = ArcFunction::new(|x: i32| x * 2);
305    /// let arc = double.to_arc();
306    ///
307    /// // Original function still usable
308    /// assert_eq!(double.apply(21), 42);
309    /// assert_eq!(arc.apply(21), 42);
310    /// ```
311    fn to_arc(&self) -> ArcFunction<T, R>
312    where
313        Self: Clone + Send + Sync + 'static,
314        T: Send + Sync + 'static,
315        R: Send + Sync + 'static,
316    {
317        self.clone().into_arc()
318    }
319
320    /// Converts function to a closure without consuming self
321    ///
322    /// **📌 Borrows `&self`**: The original function remains usable
323    /// after calling this method.
324    ///
325    /// # Default Implementation
326    ///
327    /// The default implementation creates a closure that captures a
328    /// clone of `self` and calls its `transform` method. Types can
329    /// override this method to provide more efficient conversions.
330    ///
331    /// # Returns
332    ///
333    /// Returns a closure that implements `Fn(&T) -> R`
334    ///
335    /// # Examples
336    ///
337    /// ```rust
338    /// use qubit_function::{ArcFunction, Function};
339    ///
340    /// let double = ArcFunction::new(|x: i32| x * 2);
341    /// let closure = double.to_fn();
342    ///
343    /// // Original function still usable
344    /// assert_eq!(double.apply(21), 42);
345    /// assert_eq!(closure(21), 42);
346    /// ```
347    fn to_fn(&self) -> impl Fn(&T) -> R
348    where
349        Self: Clone + 'static,
350    {
351        self.clone().into_fn()
352    }
353
354    /// Convert to FunctionOnce without consuming self
355    ///
356    /// **⚠️ Requires Clone**: This method requires `Self` to implement `Clone`.
357    /// Clones the current function and converts the clone to a one-time function.
358    ///
359    /// # Returns
360    ///
361    /// Returns a `BoxFunctionOnce<T, R>`
362    ///
363    /// # Examples
364    ///
365    /// ```rust
366    ///
367    /// fn takes_once<F: FunctionOnce<i32, i32>>(func: F, value: &i32) -> i32 {
368    ///     func.apply(value)
369    /// }
370    ///
371    /// let func = BoxFunction::new(|x: &i32| x * 2);
372    /// let result = takes_once(func.to_once(), &5);
373    /// assert_eq!(result, 10);
374    /// ```
375    fn to_once(&self) -> BoxFunctionOnce<T, R>
376    where
377        Self: Clone + 'static,
378        T: 'static,
379        R: 'static,
380    {
381        self.clone().into_once()
382    }
383}
384
385// ============================================================================
386// BoxFunction - Box<dyn Fn(&T) -> R>
387// ============================================================================
388
389/// BoxFunction - function wrapper based on `Box<dyn Fn>`
390///
391/// A function wrapper that provides single ownership with reusable
392/// transformation. The function consumes the input and can be called
393/// multiple times.
394///
395/// # Features
396///
397/// - **Based on**: `Box<dyn Fn(&T) -> R>`
398/// - **Ownership**: Single ownership, cannot be cloned
399/// - **Reusability**: Can be called multiple times (each call consumes its
400///   input)
401/// - **Thread Safety**: Not thread-safe (no `Send + Sync` requirement)
402///
403/// # Author
404///
405/// Haixing Hu
406pub struct BoxFunction<T, R> {
407    function: Box<dyn Fn(&T) -> R>,
408    name: Option<String>,
409}
410
411impl<T, R> BoxFunction<T, R> {
412    // Generates: new(), new_with_name(), new_with_optional_name(), name(), set_name()
413    impl_function_common_methods!(
414        BoxFunction<T, R>,
415        (Fn(&T) -> R + 'static),
416        |f| Box::new(f)
417    );
418
419    // Generates: when(), and_then(), compose()
420    impl_box_function_methods!(
421        BoxFunction<T, R>,
422        BoxConditionalFunction,
423        Function
424    );
425}
426
427// Generates: constant() method for BoxFunction<T, R>
428impl_function_constant_method!(BoxFunction<T, R>, 'static);
429
430// Generates: identity() method for BoxFunction<T, T>
431impl_function_identity_method!(BoxFunction<T, T>);
432
433// Generates: Debug and Display implementations for BoxFunction<T, R>
434impl_function_debug_display!(BoxFunction<T, R>);
435
436// Implement Function trait for BoxFunction<T, R>
437impl<T, R> Function<T, R> for BoxFunction<T, R> {
438    fn apply(&self, t: &T) -> R {
439        (self.function)(t)
440    }
441
442    // Generates: into_box(), into_rc(), into_fn(), into_once()
443    impl_box_conversions!(
444        BoxFunction<T, R>,
445        RcFunction,
446        Fn(&T) -> R,
447        BoxFunctionOnce
448    );
449}
450
451// ============================================================================
452// RcFunction - Rc<dyn Fn(&T) -> R>
453// ============================================================================
454
455/// RcFunction - single-threaded function wrapper
456///
457/// A single-threaded, clonable function wrapper optimized for scenarios
458/// that require sharing without thread-safety overhead.
459///
460/// # Features
461///
462/// - **Based on**: `Rc<dyn Fn(&T) -> R>`
463/// - **Ownership**: Shared ownership via reference counting (non-atomic)
464/// - **Reusability**: Can be called multiple times (each call consumes its
465///   input)
466/// - **Thread Safety**: Not thread-safe (no `Send + Sync`)
467/// - **Clonable**: Cheap cloning via `Rc::clone`
468///
469/// # Author
470///
471/// Haixing Hu
472pub struct RcFunction<T, R> {
473    function: Rc<dyn Fn(&T) -> R>,
474    name: Option<String>,
475}
476
477impl<T, R> RcFunction<T, R> {
478    // Generates: new(), new_with_name(), new_with_optional_name(), name(), set_name()
479    impl_function_common_methods!(
480        RcFunction<T, R>,
481        (Fn(&T) -> R + 'static),
482        |f| Rc::new(f)
483    );
484
485    // Generates: when(), and_then(), compose()
486    impl_shared_function_methods!(
487        RcFunction<T, R>,
488        RcConditionalFunction,
489        into_rc,
490        Function,
491        'static
492    );
493}
494
495// Generates: constant() method for RcFunction<T, R>
496impl_function_constant_method!(RcFunction<T, R>, 'static);
497
498// Generates: identity() method for RcFunction<T, T>
499impl_function_identity_method!(RcFunction<T, T>);
500
501// Generates: Clone implementation for RcFunction<T, R>
502impl_function_clone!(RcFunction<T, R>);
503
504// Generates: Debug and Display implementations for RcFunction<T, R>
505impl_function_debug_display!(RcFunction<T, R>);
506
507// Implement Function trait for RcFunction<T, R>
508impl<T, R> Function<T, R> for RcFunction<T, R> {
509    fn apply(&self, t: &T) -> R {
510        (self.function)(t)
511    }
512
513    // Use macro to implement conversion methods
514    impl_rc_conversions!(
515        RcFunction<T, R>,
516        BoxFunction,
517        BoxFunctionOnce,
518        Fn(t: &T) -> R
519    );
520}
521
522// ============================================================================
523// ArcFunction - Arc<dyn Fn(&T) -> R + Send + Sync>
524// ============================================================================
525
526/// ArcFunction - thread-safe function wrapper
527///
528/// A thread-safe, clonable function wrapper suitable for multi-threaded
529/// scenarios. Can be called multiple times and shared across threads.
530///
531/// # Features
532///
533/// - **Based on**: `Arc<dyn Fn(&T) -> R + Send + Sync>`
534/// - **Ownership**: Shared ownership via reference counting
535/// - **Reusability**: Can be called multiple times (each call consumes its
536///   input)
537/// - **Thread Safety**: Thread-safe (`Send + Sync` required)
538/// - **Clonable**: Cheap cloning via `Arc::clone`
539///
540/// # Author
541///
542/// Haixing Hu
543pub struct ArcFunction<T, R> {
544    function: Arc<dyn Fn(&T) -> R + Send + Sync>,
545    name: Option<String>,
546}
547
548impl<T, R> ArcFunction<T, R> {
549    // Generates: new(), new_with_name(), new_with_optional_name(), name(), set_name()
550    impl_function_common_methods!(
551        ArcFunction<T, R>,
552        (Fn(&T) -> R + Send + Sync + 'static),
553        |f| Arc::new(f)
554    );
555
556    // Generates: when(), and_then(), compose()
557    impl_shared_function_methods!(
558        ArcFunction<T, R>,
559        ArcConditionalFunction,
560        into_arc,
561        Function,
562        Send + Sync + 'static
563    );
564}
565
566// Generates: constant() method for ArcFunction<T, R>
567impl_function_constant_method!(ArcFunction<T, R>, Send + Sync + 'static);
568
569// Generates: identity() method for ArcFunction<T, T>
570impl_function_identity_method!(ArcFunction<T, T>);
571
572// Generates: Clone implementation for ArcFunction<T, R>
573impl_function_clone!(ArcFunction<T, R>);
574
575// Generates: Debug and Display implementations for ArcFunction<T, R>
576impl_function_debug_display!(ArcFunction<T, R>);
577
578// Implement Function trait for ArcFunction<T, R>
579impl<T, R> Function<T, R> for ArcFunction<T, R> {
580    fn apply(&self, t: &T) -> R {
581        (self.function)(t)
582    }
583
584    // Use macro to implement conversion methods
585    impl_arc_conversions!(
586        ArcFunction<T, R>,
587        BoxFunction,
588        RcFunction,
589        BoxFunctionOnce,
590        Fn(t: &T) -> R
591    );
592}
593
594// ============================================================================
595// Blanket implementation for standard Fn trait
596// ============================================================================
597
598// Implement Function<T, R> for any type that implements Fn(&T) -> R
599impl_closure_trait!(
600    Function<T, R>,
601    apply,
602    BoxFunctionOnce,
603    Fn(input: &T) -> R
604);
605
606// ============================================================================
607// FnFunctionOps - Extension trait for closure functions
608// ============================================================================
609
610// Generates: FnFunctionOps trait and blanket implementation
611impl_fn_ops_trait!(
612    (Fn(&T) -> R),
613    FnFunctionOps,
614    BoxFunction,
615    Function,
616    BoxConditionalFunction
617);
618
619// ============================================================================
620// BoxConditionalFunction - Box-based Conditional Function
621// ============================================================================
622
623/// BoxConditionalFunction struct
624///
625/// A conditional function that only executes when a predicate is satisfied.
626/// Uses `BoxFunction` and `BoxPredicate` for single ownership semantics.
627///
628/// This type is typically created by calling `BoxFunction::when()` and is
629/// designed to work with the `or_else()` method to create if-then-else logic.
630///
631/// # Features
632///
633/// - **Single Ownership**: Not cloneable, consumes `self` on use
634/// - **Conditional Execution**: Only transforms when predicate returns `true`
635/// - **Chainable**: Can add `or_else` branch to create if-then-else logic
636/// - **Implements Function**: Can be used anywhere a `Function` is expected
637///
638/// # Examples
639///
640/// ## With or_else Branch
641///
642/// ```rust
643/// use qubit_function::{Function, BoxFunction};
644///
645/// let double = BoxFunction::new(|x: i32| x * 2);
646/// let negate = BoxFunction::new(|x: i32| -x);
647/// let conditional = double.when(|x: &i32| *x > 0).or_else(negate);
648///
649/// assert_eq!(conditional.apply(5), 10); // when branch executed
650/// assert_eq!(conditional.apply(-5), 5); // or_else branch executed
651/// ```
652///
653/// # Author
654///
655/// Haixing Hu
656pub struct BoxConditionalFunction<T, R> {
657    function: BoxFunction<T, R>,
658    predicate: BoxPredicate<T>,
659}
660
661// Use macro to generate conditional function implementations
662impl_box_conditional_function!(
663    BoxConditionalFunction<T, R>,
664    BoxFunction,
665    Function
666);
667
668// Use macro to generate conditional function debug and display implementations
669impl_conditional_function_debug_display!(BoxConditionalFunction<T, R>);
670
671// ============================================================================
672// RcConditionalFunction - Rc-based Conditional Function
673// ============================================================================
674
675/// RcConditionalFunction struct
676///
677/// A single-threaded conditional function that only executes when a
678/// predicate is satisfied. Uses `RcFunction` and `RcPredicate` for shared
679/// ownership within a single thread.
680///
681/// This type is typically created by calling `RcFunction::when()` and is
682/// designed to work with the `or_else()` method to create if-then-else logic.
683///
684/// # Features
685///
686/// - **Shared Ownership**: Cloneable via `Rc`, multiple owners allowed
687/// - **Single-Threaded**: Not thread-safe, cannot be sent across threads
688/// - **Conditional Execution**: Only transforms when predicate returns `true`
689/// - **No Lock Overhead**: More efficient than `ArcConditionalFunction`
690///
691/// # Examples
692///
693/// ```rust
694/// use qubit_function::{Function, RcFunction};
695///
696/// let double = RcFunction::new(|x: i32| x * 2);
697/// let identity = RcFunction::<i32, i32>::identity();
698/// let conditional = double.when(|x: &i32| *x > 0).or_else(identity);
699///
700/// let conditional_clone = conditional.clone();
701///
702/// assert_eq!(conditional.apply(5), 10);
703/// assert_eq!(conditional_clone.apply(-5), -5);
704/// ```
705///
706/// # Author
707///
708/// Haixing Hu
709pub struct RcConditionalFunction<T, R> {
710    function: RcFunction<T, R>,
711    predicate: RcPredicate<T>,
712}
713
714// Use macro to generate conditional function implementations
715impl_shared_conditional_function!(
716    RcConditionalFunction<T, R>,
717    RcFunction,
718    Function,
719    'static
720);
721
722// Use macro to generate conditional function clone implementations
723impl_conditional_function_clone!(RcConditionalFunction<T, R>);
724
725// Use macro to generate conditional function debug and display implementations
726impl_conditional_function_debug_display!(RcConditionalFunction<T, R>);
727
728// ============================================================================
729// ArcConditionalFunction - Arc-based Conditional Function
730// ============================================================================
731
732/// ArcConditionalFunction struct
733///
734/// A thread-safe conditional function that only executes when a predicate is
735/// satisfied. Uses `ArcFunction` and `ArcPredicate` for shared ownership
736/// across threads.
737///
738/// This type is typically created by calling `ArcFunction::when()` and is
739/// designed to work with the `or_else()` method to create if-then-else logic.
740///
741/// # Features
742///
743/// - **Shared Ownership**: Cloneable via `Arc`, multiple owners allowed
744/// - **Thread-Safe**: Implements `Send + Sync`, safe for concurrent use
745/// - **Conditional Execution**: Only transforms when predicate returns `true`
746/// - **Chainable**: Can add `or_else` branch to create if-then-else logic
747///
748/// # Examples
749///
750/// ```rust
751/// use qubit_function::{Function, ArcFunction};
752///
753/// let double = ArcFunction::new(|x: i32| x * 2);
754/// let identity = ArcFunction::<i32, i32>::identity();
755/// let conditional = double.when(|x: &i32| *x > 0).or_else(identity);
756///
757/// let conditional_clone = conditional.clone();
758///
759/// assert_eq!(conditional.apply(5), 10);
760/// assert_eq!(conditional_clone.apply(-5), -5);
761/// ```
762///
763/// # Author
764///
765/// Haixing Hu
766pub struct ArcConditionalFunction<T, R> {
767    function: ArcFunction<T, R>,
768    predicate: ArcPredicate<T>,
769}
770
771// Use macro to generate conditional function implementations
772impl_shared_conditional_function!(
773    ArcConditionalFunction<T, R>,
774    ArcFunction,
775    Function,
776    Send + Sync + 'static
777);
778
779// Use macro to generate conditional function clone implementations
780impl_conditional_function_clone!(ArcConditionalFunction<T, R>);
781
782// Use macro to generate conditional function debug and display implementations
783impl_conditional_function_debug_display!(ArcConditionalFunction<T, R>);