Rust
Rustで関数をカリー化してみる
Rustで関数をカリー化してみた。
第一級関数をサポートしている言語なら関数のカリー化が可能なはずだ。
つまりラムダ式が作れて、クロージャ機能かキャプチャ機能があって、それを関数から返せる言語であれば、基本的にどんな言語でも関数をカリー化することができる。
Rustは関数がクロージャになることができないが、キャプチャ機能があるラムダ式が作れる言語なので、関数のカリー化が可能だ。(Rustはラムダ式をクロージャと呼ぶが、機能はラムダ式と変わらない)
そもそもカリー化とは何かというと、複数の引数をとる関数を「最後の引数以外を与えて呼び出せば、それらの引数を見えないところに保持しておいて、残り一つの引数だけ渡せば結果が得られる関数を返すよ」という関数にすることだ。
これは日本語なのか?というくらい回りくどい言い方になる。
もう少し簡潔に言うと複数の引数をとる関数を、最後以外の引数を見えないところに保持しておいて、最後の引数一つだけ与えれば結果が得られるラムダ式を返す関数にすることだ。
これでもややこしい。
見えないところってどこよ?となるのだが、Rustの場合はラムダ式がキャプチャした値として保持される。(JavaScriptの場合はクロージャに保持される)
これの何が嬉しいのかというと、例えば「2つの引数のうち最初の引数が毎回同じとき、呼び出す度にそれを何度も書かなくても済むようになる」という関数が得られることだ。
毎回同じなら引数にせずに関数内に定数を書いとけば良いじゃん、と思うかもしれないが、例えば10回呼び出した後は最初の引数を変えなくてはならない、という場合などに役立つわけだ。
ということでカリー化してみる。
下のような関数がある。
引数を2つ取り、2つの値を足した結果を返す、という関数だ。
この関数を使って、最初の2回は5に何かを足す、そして次の2回は10に何かを足す、という計算をさせるとする。
上のように書いてもまったく問題はないのだが、この関数をカリー化すると「5に何かを足す」関数と「10に何かを足す」関数という2つの関数が得られる関数にすることができる。
こんな感じだ。
上コードの add_five() や add_ten() という関数を得ることがカリー化なのではなく、最初の add_func() を add_n_func() の形に変えてあげることをカリー化という。(add_five() や add_ten() を得ることは部分適用という)
|