📜  rust Currying 将一个多参数函数更改为一个预先设置了一些参数的函数. - Rust (1)

📅  最后修改于: 2023-12-03 15:04:57.609000             🧑  作者: Mango

Rust Currying

Currying is a technique where you can transform a multiple-parameter function into a function that takes the first argument and returns a new function that takes the second argument and so on until all arguments have been consumed. This technique is named after Haskell Curry, a mathematician who made significant contributions in the field of logic and computer science.

In Rust, we can use closures to implement currying. Here is an example:

fn add(x: i32, y: i32, z: i32) -> i32 {
    x + y + z
}

fn main() {
    let add1 = |x| {
        let add2 = |y| {
            let add3 = |z| {
                add(x, y, z)
            };
            add3
        };
        add2
    };

    let result = add1(1)(2)(3);
    println!("{}", result); // prints "6"
}

In this example, we have defined a function add that takes three arguments and returns their sum. In the main function, we have created a closure add1 that takes the first argument x and returns a new closure add2 that takes the second argument y and returns a new closure add3 that takes the third argument z and finally invokes the original function add with all three arguments.

Note that we invoke the closures by chaining them using parentheses, as in add1(1)(2)(3). This is because each closure returns a new closure that takes the next argument.

Currying can be useful when we have functions that take a large number of arguments, as it allows us to partially apply some arguments and reuse the resulting functions in different contexts.

In Rust, we can also use the curry method from the funty crate to automatically curry functions. Here is an example:

use funty::curry;

fn add(x: i32, y: i32, z: i32) -> i32 {
    x + y + z
}

fn main() {
    let add1 = curry(add);
    let add2 = add1(1);
    let add3 = add2(2);

    let result = add3(3);
    println!("{}", result); // prints "6"
}

In this example, we import the curry function from the funty crate and use it to transform the add function into a curried version. Then, we create new functions add1, add2, and add3 by partially applying the arguments of the original function.

Note that the curry method creates a closure that takes the arguments in the order they appear in the original function signature. If we want to specify a different order, we can use the flip method from the same crate.

use funty::curry;
use funty::flip;

fn div(x: f64, y: f64) -> f64 {
    x / y
}

fn main() {
    let div1 = curry(div);
    let div2 = flip(div1(2.0));

    let result = div2(10.0);
    println!("{}", result); // prints "5.0"
}

In this example, we define a division function that takes two arguments and returns their quotient. We use the curry function to transform it into a curried version and the flip function to flip the order of the arguments, creating a new function div2 that takes the second argument first and the first argument second.

Currying is a powerful technique that can simplify our code and make it more composable and reusable. Rust provides several ways to implement currying, including manual closure chaining and the curry and flip functions from external crates.