ただのクロージャとカリー化の違いがよくわからない
補足
なんかブクマ数が増えている・・・・
当時は区別がつかなかったんだよ。
自分の中で整理がやっとついたんで説明しなおしています。
http://prezi.com/9brwewgcxtr2/javascript/
ただのクロージャとカリー化の違いがよくわからない。
ラムダとクロージャの違い
ただのラムダとクロージャの違いはキャプチャするかしないかで判別できると思う。
パラメータをキャプチャしないのがラムダ。
パラメータをキャプチャできるのがクロージャ。
//これはキャプチャしないのでラムダ var myfunc = function(a,b) { return a + b; }
//これはcaptureをキャプチャするのでクロージャ var capture = 123; var myfunc = function(a,b) { return a + b + capture; }
違いはパラメータをキャプチャできるかどうか
クロージャとカリー化の違い
では、クロージャとカリー化の違いは何?
クロージャの中で新たに生成した関数を返すこと?
だけど何か違う気がする。
wikipediaのカリー化の項目を見てみる。
http://ja.wikipedia.org/wiki/%E3%82%AB%E3%83%AA%E3%83%BC%E5%8C%96
複数の引数をとる関数を、引数が「もとの関数の最初の引数」で戻り値が「もとの関数の残りの引数を取り結果を返す関数」であるような関数にすること。
クロージャの中で関数を生成して返せばいいというものではないらしい。
悩んでいるうちに見つけた、檜山正幸のキマイラ飼育記のJavaScriptでカリー化を見て納得した。
http://d.hatena.ne.jp/m-hiyama/20051213/1134446855
//これがオリジナル function sum(x,y) { return x + y; }
↓
//カリー化 function curreied_sum(x) { return function (y) { return x + y; }; }
なるほど。とても分かりやすい。
ようするに、クロージャを利用して、元の関数の引数を減らせばカリー化になのかな。
だけど、ここで疑問が生まれる。
・引数が1つの関数を変換してもカリー化とはいわないの?
・元の関数の複数の引数を減らした場合はカリー化といえるの?
・元の関数の先頭の引数以外を減らした場合もカリー化といえるの?
・元の関数の複数の引数をすべて減らした場合もカリー化といえるの?
上から見ていく。
引数が1つの関数を変換してもカリー化とはいわないの?
//二乗する function pow(x) { return x * x; }
↓
//カリー化?? function curreied_pow(x) { return function () { return x * x; }; }
これはどうなんだろう。
wikipediaの説明を見ると、複数の引数をとる関数を〜と書いてある。
複数の引数をとる関数を、引数が「もとの関数の最初の引数」で戻り値が「もとの関数の残りの引数を取り結果を返す関数」であるような関数にすること。
と、いうことは単一の引数を取る関数をこうやって変換しても、これはカリー化ではないわけか?
元の関数の複数の引数を減らした場合はカリー化といえるの?
//これがオリジナル function sum3(x,y,z) { return x + y + z; }
↓
//カリー化?? //パラメータ x y z のうち x と yを消す function curreied_sum3(x,y) { return function (z) { return x + y + z; }; }
これはどうなんだろう。
wikipediaの説明を見ると、、、問題がないように見える。
一つだけ消すとはどこにも書いてない。
複数の引数をとる関数を、引数が「もとの関数の最初の引数」で戻り値が「もとの関数の残りの引数を取り結果を返す関数」であるような関数にすること。
つまり、複数消しても大丈夫。カリー化したといえるのかな。
元の関数の先頭の引数以外を減らした場合もカリー化といえるの?
//これがオリジナル function sum3(x,y,z) { return x + y + z; }
↓
//カリー化?? //パラメータ x y z のうち z を消す function curreied_sum3(z) { return function (x,y) { return x + y + z; }; }
これはどうなんだろう。
wikipediaの説明を見ると、、、もとの関数の最初の引数と書いてある。
それだとこれはカリー化ではない?
複数の引数をとる関数を、引数が「もとの関数の最初の引数」で戻り値が「もとの関数の残りの引数を取り結果を返す関数」であるような関数にすること。
なんか納得いかない。
wikiepdiaでは〜ような関数にすることとあるので、最初以外を消しても大丈夫な気もする。
教えて偉い人。
元の関数の複数の引数をすべて減らした場合もカリー化といえるの?
//これがオリジナル function sum3(x,y,z) { return x + y + z; }
↓
//カリー化?? //パラメータ x y z のうち x,y,z を消す function curreied_sum3(x,y,z) { return function () { return x + y + z; }; }
これはどうなんだろう。
wikipediaの説明を見ると、、、もとの関数の残りの引数を取り結果を返す関数と書いてある。
これって引数が1つの関数をカリー化できるのかという問題と同じような気もするんね。
カリー化ではない?
複数の引数をとる関数を、引数が「もとの関数の最初の引数」で戻り値が「もとの関数の残りの引数を取り結果を返す関数」であるような関数にすること。
カリー化のメリット
ラムダのメリットはよく分かる。いちいち名前をつけた関数を定義しないでもOKで楽チンだ。
クロージャのメリットもよく分かる。変数をキャプチャできるのでとてもプログラムが書きやすい。
#ただし、スパゲティ度も上がる気がするw
では、カリー化のメリットは?
パラメータをひとつ減らせるので使う側は便利。
でも、それってラッパー作れば良くない?
//これがオリジナル function sum(x,y) { return x + y; }
↓
//カリー化 function curreied_sum(x) { return function (y) { return x + y; }; }
//ラッパー function wrapper_sum(y) { return 123 + y }
おっと、123は即値なので、これでは汎用性が下がってしまう。
クラスにでもして汎用性をもたせるか、、、
//ラッパー function wrapper_sum(x) { this.x = x; this.sum = function (y) { return this.x + y }; }
メンドイ。
なるほど。カリー化は偉大だわ。。。