curry_macro/
lib.rs

1#![no_std]
2/// Create a curried function
3/// 
4/// Example:
5/// 
6/// You can curry an add function that adds two numbers.
7/// 
8/// Simplest form, without any type annotations.
9/// You need to use the curried function so that
10/// the rust compiler can infer the input and return
11/// types for you:
12/// ```
13/// # use curry_macro::curry;
14/// let add = curry!(|a, b| a + b);
15/// assert_eq!(add(1)(2), 3);
16/// ```
17/// With input type annotations:
18/// ```
19/// # use curry_macro::curry;
20/// let add = curry!(|a: i32, b: i32| a + b);
21/// ```
22/// With input and return type annotations and a block as function body
23/// ```
24/// # use curry_macro::curry;
25/// let add = curry!(|a: i32, b: i32| -> i32 { a + b });
26/// ```
27/// The above three functions work the same:
28/// ```
29/// # use curry_macro:: curry;
30/// # let add = curry!(|a, b| a + b);
31/// // You can generate intermediate functions that are partially applied:
32/// let add1_to = add(1);
33/// let sum = add1_to(2);
34/// assert_eq!(sum, 3);
35/// // You can also can apply all arguments at once:
36/// let sum = add(1)(2);
37/// assert_eq!(sum, 3);
38/// ```
39#[macro_export]
40macro_rules! curry (
41   // Simplest form, without any type annotations.
42    (|$first_arg:ident $(, $arg:ident )*| $function_body:expr) => {
43       move |$first_arg| $(move |$arg|)* {
44          $function_body
45       }
46    };
47    // With input type annotations
48    (|$first_arg:ident:$first_arg_type:ty $(, $arg:ident:$arg_type:ty )*| $function_body:expr) => {
49      move |$first_arg:$first_arg_type| $(move |$arg:$arg_type|)* {
50         $function_body
51      }
52   };
53   // With input and return type annotations and a block as function body
54   (|$first_arg:ident:$first_arg_type:ty $(, $arg:ident:$arg_type:ty )*| -> $ret_type:ty $function_body:block) => {
55    move |$first_arg:$first_arg_type| $(move |$arg:$arg_type|)* -> $ret_type {
56       $function_body
57    };
58   };
59);