如何创建一个带有多个参数的函数并为该函数提供第一个参数的宏?

时间:2019-01-16 16:19:36

标签: functional-programming rust currying

我希望能够创建一个接受函数(称为g)的高阶函数(称为f)。 g应该将第一个参数传递给f并返回一个新函数。

用例是我想在g中启动数据库连接,并传递接受数据库连接的功能。

fn f1(a: i32, b: String) -> String {
    b
}

fn f2(a: i32, c: i64, d: i16) -> i32 {
    1000
}

fn g<T>(f: fn(a: i32, arbitrary_arguments_type) -> T) -> fn(arbitrary_arguments_type) -> T {
    move |arbitrary_arguments| f(1, arbitrary_arguments)
}

fn main() {
    g(f1)("hello".to_string());
    g(f2)(10, 11);
}

如何创建一个宏,该宏将具有多个参数的函数作为参数接受,其中第一个参数是某种类型,并为第一个函数提供该参数?

1 个答案:

答案 0 :(得分:1)

  

我要解决的具体问题是如何创建一个宏,该宏将具有多个参数的函数作为参数接受,其中第一个参数是某种类型,为该第一个函数提供该参数。 / p>

宏(甚至是程序宏)在语法树上运行,因此它们无法基于语义(包括类型和函数一致性)更改其行为。这意味着您必须为每个可能数量的参数使用一个不同的宏。例如:

macro_rules! curry1 {
    ($func: ident, $($arg: expr),*) => {
        |a| $func($($arg),*, a)
    }
}

macro_rules! curry2 {
    ($func: ident, $($arg: expr),*) => {
        |a, b| $func($($arg),*, a, b)
    }
}

macro_rules! curry3 {
    ($func: ident, $($arg: expr),*) => {
        |a, b, c| $func($($arg),*, a, b, c)
    }
}

将这样使用:

fn f(a: i32, b: i32, c: i32) -> i32 {
    a + b + c
}

fn main() {
    // requires 2 extra args
    let f_2 = curry2!(f, 2);
    // requires 1 extra arg
    let f_2_1 = curry1!(f, 2, 1);

    println!("{}", f(2, 1, 3)); // 6
    println!("{}", f_2(1, 3));  // 6
    println!("{}", f_2_1(3));   // 6
}