auto_currying/
lib.rs

1pub trait Curry<'a, T> {
2    type Output;
3    fn curry(self) -> Self::Output;
4}
5macro_rules! gen_impl {
6	(OUT $l:lifetime $id:ident, $ret:ident)=>{
7		Box<dyn FnOnce($id)->$ret + $l>
8	};
9	(OUT $l:lifetime $id:ident $($tail:ident)+,$ret:ident) => {
10		Box<dyn FnOnce($id)->gen_impl!(OUT $l $($tail)+,$ret) + $l>
11	};
12	(FUNC $id:ident,$ret:ident {$meta:ident, $($para:ident)+})=>{
13		Box::new(move |$id|{
14			$meta($($para),+)
15		})
16	};
17	(FUNC $id:ident $($tail:ident)+,$ret:ident {$meta:ident, $($para:ident)+})=>{
18		Box::new(move |$id|{
19           gen_impl!(FUNC $($tail)+, $ret {$meta, $($para)+})
20		})
21	};
22}
23macro_rules! gen_curry {
24	($($t:ident)+) => {
25		#[allow(non_snake_case)]
26		impl<'a,$($t),+,F:'a,Ret>  Curry<'a,($($t),+,F,Ret)> for F
27		where F:FnOnce($($t),+)->Ret,
28		      $($t:'a),+
29		{
30			type Output = gen_impl!(OUT 'a $($t)+,Ret);
31			fn curry(self)->Self::Output{
32				gen_impl!(FUNC $($t)+, Ret {self, $($t)+})
33			}
34		}
35	};
36}
37
38macro_rules! impl_curry{
39	($($($id:ident)+),*)=>{
40		$(gen_curry!($($id)+);)*
41	};
42}
43
44impl_curry! {
45    T0,
46    T0 T1,
47    T0 T1 T2,
48    T0 T1 T2 T3,
49    T0 T1 T2 T3 T4,
50    T0 T1 T2 T3 T4 T5,
51    T0 T1 T2 T3 T4 T5 T6,
52    T0 T1 T2 T3 T4 T5 T6 T7,
53    T0 T1 T2 T3 T4 T5 T6 T7 T8,
54    T0 T1 T2 T3 T4 T5 T6 T7 T8 T9,
55    T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10,
56    T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11
57}
58
59#[cfg(test)]
60mod test {
61    use crate::Curry;
62    #[test]
63    fn test() {
64        fn fun(_i: i32) -> i32 {
65            0
66        }
67        let c1 = fun.curry();
68        assert_eq!(c1(1), 0);
69        fn fun2(_i: i32, _i2: f64) -> bool {
70            false
71        }
72        let c1 = fun2.curry();
73        assert_eq!(c1(1)(2.0), false);
74        fn fun6(_i: (), _i2: (), _i3: (), _: (), _: (i32, u8), _: &str) {}
75        let c1 = fun6.curry();
76        assert_eq!(c1(())(())(())(())((1, 2))("hello"), ());
77    }
78}