最終更新:2017-11-17 (金) 12:03:49 (2514d)
クロージャ
Top / クロージャ
- ローカル変数を参照している関数内関数
クロージャは元々、最も有名な関数型プログラミング言語の 1 つである Scheme の一部として 1960年代に開発されました。ラムダ関数とクロージャが頻繁に登場する言語としては、関数をファーストクラスの値として扱える言語 (つまり関数がオンザフライで作成され、パラメーターとして他の言語に渡される言語) があります。
概要
- 関数自身が定義された環境を、ローカル変数も含めて持ち運ぶことのできる仕組み (またはそうした関数自体)
- 関数呼び出しが終わってもローカル変数を参照し続けられる
ラムダ関数
- ラムダ関数そのものによって、これまでなかったものが新たに大量に追加されるわけではありません。しかしラムダ関数は何と言っても使い捨て関数であり、何の状態も保持しないため、できることは限られます。そこでクロージャが登場し、ラムダ関数を次のレベルにまで高めるのです。
特徴
- 関数呼び出しが終わってもローカル変数を参照し続けられる
JavaScript/クロージャ
- JavaScriptでは、スコープチェーンの仕組みがそのままクロージャの実現へとつながっている
function newCounter() { var i = 0; return function() { // 無名関数 i = i + 1;//newCounterのローカル変数iを参照 return i; } } c1 = newCounter(); alert(c1()); // 1 alert(c1()); // 2 alert(c1()); // 3 alert(c1()); // 4 alert(c1()); // 5
- 関数呼び出し時点における変数名解決の環境を保持した関数
- 内側の関数のスコープチェーンのために外側の関数も必要
PHP
$string = "Hello World!"; $closure = function() use ($string) { echo $string; }; $closure(); // Hello World!
ラムダが無名関数にすぎないのであれば、クロージャはラムダに少しコンテキストが追加された程度のものにすぎません。つまりクロージャは無名関数であり、作成されると、その無名関数を作成したコードのスコープの変数の値を、その無名関数自体に追加します。変数は use キーワードによってクロージャーにバインドされます。
外部の環境からインポートされる変数は、クロージャー関数を定義する use 節の中で規定されています。デフォルトで、変数は値で渡されます。つまりクロージャー関数の定義の中で渡される値を更新した場合、外部の値は更新されません。しかし & 演算子を変数の前に付けると (& 演算子は参照で渡すことを示すために関数定義の中で使われます)、外部の値も更新することができます。
- http://www.ibm.com/developerworks/jp/opensource/library/os-php-5.3new2/
- http://www.ibm.com/developerworks/jp/opensource/library/os-php-lambda/
関連
メモ
- 関数クロージャの機構は、関数のカリー化と呼ばれる機構と本質的に等価。
- http://hisasann.com/housetect/2007/12/post_44.html