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}