mcurry/
curry.rs

1/// Creates a curried function.
2///
3/// The given function definition should be specified in the form
4///
5/// ```text
6/// (arg ->)+ (*|@return_type) {
7///     function_body
8/// }
9/// ```
10///
11/// No types are specified on the function parameters. An explicit return type can be specified
12/// with a type preceded by an `@`; specifying `*` will deduce the return type. The macro will not
13/// perform any type conversions.
14///
15/// # Examples
16///
17/// ```
18/// # #[macro_use] extern crate mcurry;
19/// # fn main() {
20/// let add_3 = curry!(a -> b -> c -> * {
21///   a + b + c
22/// });
23///
24/// assert_eq!(add_3(13)(71)(26), 110);
25/// # }
26/// ```
27///
28/// ```
29/// # #[macro_use] extern crate mcurry;
30/// # fn main() {
31/// let haiku = curry!(a -> b -> c -> @String {
32///   let lines = vec![a, b, c];
33///   lines.join("\n")
34/// });
35///
36/// assert_eq!(haiku("The first cold shower")
37///                 ("Even the monkey seems to want")
38///                 ("A little coat of straw"),
39///
40///                 "The first cold shower\n\
41///                  Even the monkey seems to want\n\
42///                  A little coat of straw");
43/// # }
44/// ```
45///
46/// ```compile_fail
47/// # #[macro_use] extern crate mcurry;
48/// # fn main() {
49/// let add_3 = curry!(a -> b -> c -> @usize {
50///   a + b + c // error; evaluates to i32
51/// });
52///
53/// assert_eq!(add_3(13)(71)(26), 110);
54/// # }
55/// ```
56#[macro_export]
57macro_rules! curry(
58    ($($arg:ident ->)+ * $body:block) => {
59        $(move |$arg|)* $body
60    };
61
62    ($($arg:ident ->)+ @$ret:ty $body:block) => {
63        $(move |$arg|)* -> $ret { $body }
64    };
65);
66
67#[cfg(test)]
68mod test {
69    #[test]
70    fn test_return_elided() {
71        let div_minus = curry!(n -> m -> o -> * {
72            let div = n / m;
73            div - o
74        });
75        assert_eq!(div_minus(100)(4)(5), 20);
76    }
77
78    #[test]
79    fn test_return_specified() {
80        let div_minus = curry!(n -> m -> o -> @i32 {
81            let div = n / m;
82            div - o
83        });
84        assert_eq!(div_minus(100)(4)(5), 20);
85    }
86}