hibit_tree/utils/
function.rs

1/// Implementable nullary [Fn].
2/// 
3/// Closures and nullary `fn`s implement it.
4pub trait NullaryFunction {
5    type Output;
6    fn exec(&self) -> Self::Output;
7}
8
9impl<F, Out> NullaryFunction for F
10where
11    F: Fn() -> Out
12{
13    type Output = Out;
14
15    #[inline]
16    fn exec(&self) -> Self::Output {
17        self()
18    }
19}
20
21/// Implementable unary [Fn].
22/// 
23/// Closures and unary `fn`s implement it.
24pub trait UnaryFunction<Arg> {
25    type Output;
26    fn exec(&self, arg: Arg) -> Self::Output;
27}
28
29impl<F, Arg, Out> UnaryFunction<Arg> for F
30where
31    F: Fn(Arg) -> Out
32{
33    type Output = Out;
34
35    #[inline]
36    fn exec(&self, arg: Arg) -> Self::Output {
37        self(arg)
38    }
39}
40
41/// Implementable binary [Fn].
42/// 
43/// Closures and binary `fn`s implement it.
44pub trait BinaryFunction<Arg0, Arg1> {
45    type Output;
46    fn exec(&self, arg0: Arg0, arg1: Arg1) -> Self::Output;
47}
48
49impl<F, Arg0, Arg1, Out> BinaryFunction<Arg0, Arg1> for F
50where
51    F: Fn(Arg0, Arg1) -> Out
52{
53    type Output = Out;
54
55    #[inline]
56    fn exec(&self, arg0: Arg0, arg1: Arg1) -> Self::Output {
57        self(arg0, arg1)
58    }
59}
60
61/// Generates stateless generic [UnaryFunction]. Ala generic closure.
62/// 
63/// # Syntax
64/// 
65/// ```text
66/// fun!([generics list] |argument: type| -> type { .. }
67/// fun!([generics list] |argument: type| where [where bounds] -> type { .. }
68/// ```
69/// 
70/// # Examples
71/// 
72/// ```
73/// # use hibit_tree::fun;
74/// # use hibit_tree::utils::Primitive;
75/// fun!(['a, T: Primitive, I: Iterator<Item=&'a T>] |xs: I| -> T {
76///     xs.fold(T::ZERO, |acc, v| acc + *v) 
77/// });
78/// ```
79/// 
80/// With `where` bounds:
81/// 
82/// ```
83/// # use hibit_tree::fun;
84/// # use hibit_tree::utils::Primitive;
85/// fun!(['a, T, I] |xs: I| -> T where [T: Primitive, I: Iterator<Item=&'a T>] {
86///     xs.fold(T::ZERO, |acc, v| acc + *v) 
87/// });
88/// ```
89#[macro_export]
90macro_rules! fun {
91    // --- UnaryFunction ---
92
93    ([$($generics:tt)*] |$arg:ident: $arg_type:ty| -> $output:ty $body:block) => {
94        fun!([$($generics)*] |$arg: $arg_type| -> $output where [] $body)
95    };
96    
97    ([$($generics:tt)*] |$arg:ident: $arg_type:ty| -> $output:ty where [$($bounds:tt)*] $body:block) => {
98        {
99            struct F;
100            impl<$($generics)*> $crate::utils::function::UnaryFunction<$arg_type> for F
101            where
102                $($bounds)*
103            {
104                type Output = $output;
105    
106                #[inline]
107                fn exec(&self, mut $arg: $arg_type) -> Self::Output {
108                    $body
109                }
110            }
111            F
112        }
113    };
114}