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