Cover Image for [Rust] カリー化(currying)と部分適用(partial application)

[Rust] カリー化(currying)と部分適用(partial application)

概要

Rustでカリー化(currying)と部分適用(partial application)ができるのか試してみた。結論としては可能。

ところでカリー化(currying)/部分適用(partial application)って何?

カリー化(Wikipedia)では以下のように説明されています

カリー化 (currying, カリー化された=curried) とは、複数の引数をとる関数を、引数が「もとの関数の最初の引数」で戻り値が「もとの関数の残りの引数を取り結果を返す関数」であるような関数にすること(あるいはその関数のこと)である。

部分適用とは、複数の引数をとる関数の一部の引数に実引数を適用する操作のこと

詳しくは関数型プログラミングの基礎的なところを勉強すると出てくると思います。自分は以下の本で学びましたがすごく良い本でした。(絶版になったのかkindle版がなくなったっぽいです...)

Rust で試す

元になる実装

以後の例で使うコード例を示す。 ただ足し算するだけの関数addを対象にします。

fn main() {
    let r = add(1, 2);
    println!("{}", r); // 3
}

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

カリー化(currying)

fn main() {
    let c_add = curry_add(1);
    let r1 = c_add(4); 
    let r2 = c_add(5);
    println!("{}", r1); // 5
    println!("{}", r2); // 6
}

fn curry_add(n: i32) -> impl Fn(i32) -> i32 {
  move |x| x + n
}

closure に引数を move することで新たな関数を生成することで、カリー化(currying) できる

部分適用(partial application)

fn main() {
    let c_add = move |x| add(1, x);
    let r1 = c_add(4); 
    let r2 = c_add(5);
    println!("{}", r1); // 5
    println!("{}", r2); // 6
}

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

こっちも closure に引数を move することで部分適用できる。個人的にはこっちの方が使い所多そう。

参考