しびら

技術ネタのメモとか。

JavaScriptでカリー化を理解する

   

1a5aab66-8eaf-1684-01f1-923f07c3f971

完全適用と部分適用

完全適用(full application)はいわゆる関数です。部分適用(partical application)は、引数の一部を渡すことをいいます。部分適用である関数add4は第1引数は固定の値で、第2引数のみ渡しています。

ちなみに、Javaでは、同じ名前であるが引数が異なる関数名(メソッド名)は宣言することができますが、JavaScriptは同じ関数名を設定することはできません。function式の場合は変数名が重複しますし、function文の場合は後勝ちとなるようです。

以下はfunction文の記述の順番を入れ替えてみた場合。実行されている関数が変わっているのがわかりますね。

ちょっと話が逸れましたが、完全適用と部分適用は以上です。

カリー化

カリー化とは、Wikipediaによると以下。

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

https://ja.wikipedia.org/wiki/%E3%82%AB%E3%83%AA%E3%83%BC%E5%8C%96

更に、以下のサイトではもう少しわかりやすく、このように記載されています。

「カリー化する」という用語は、すくなくとも以下の3つの意味で使われているようだ。

  1. 部分適用という意味
    • これは明らかに間違い
  2. 「複数の引数を取る関数」を「一引数を取る関数のチェインに直す」こと
    • これはkmizuさんの定義。世間でもよく使われる。
  3. 「構造体を一つ取る関数」を「構造体のメンバーを複数の引数にばらし、一引数を取る関数のチェインに直す」こと

「部分適用」の意味で使うのは明らかに間違いのなで排除。

http://d.hatena.ne.jp/kazu-yamamoto/20110906/1315279311

 

サンプルとして作成した、カリー化されたコードを確認してみます。以下は足し算のコードです。

add関数は無名関数を返します。無名関数は「(2)」を引数として実行され、a+bの足し算が行われ、結果が戻り値としてresultに格納されます。定義2の「引数を取る関数のチェイン」となっているのでカリー化されていますね。

 

カリー化のメリット

ではカリー化のメリットは何でしょうか。それは、部分適用で、例えば以下のmap関数(関数fと配列を与えると、配列全てに関数fを適用する)に先程作成したadd関数をそのまま使用できます。

先程作成したadd関数を含めて、実行してみましょう。

配列[3,4,5]が全て1加算されて[4,5,6]という値となりました。カリー化されていないadd関数ではこの方法で記述することはできず、forループを記述して配列を操作するindex変数を回して、、、とリーダブルで無いコードとなっていたでしょうね。

以前紹介したlodash.jsですが、lodashの第二引数に今回作成したカリー化された関数を与えることができます。

カリー化を理解すると、既存のカリー化された関数とlodash.jsを組み合わせての開発が捗りそうです。

 

すごいHaskellたのしく学ぼう!

 

 - Javascript , ,