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}