ただのクロージャとカリー化の違いがよくわからない

補足

なんかブクマ数が増えている・・・・
当時は区別がつかなかったんだよ。


自分の中で整理がやっとついたんで説明しなおしています。
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
	};
}

メンドイ。

なるほど。カリー化は偉大だわ。。。