クロージャ

クロージャ（クロージャー、）、関数閉包はプログラミング言語における関数オブジェクトの一種。いくつかの言語ではラムダ式や無名関数にて利用可能な機能・概念である。引数以外の変数を実行時の環境ではなく、自身が定義された環境（静的スコープ）において解決することを特徴とする。関数とそれを評価する環境のペアであるともいえる。この概念は少なくとも1960年代のSECDマシンまで遡ることができる。まれに、関数ではなくとも、環境に紐付けられたデータ構造のことをクロージャと呼ぶ場合もある。クロージャをサポートする言語によるプログラミングでは、単に関数の中に関数を定義することができるだけでなく、その際に、外側の関数（エンクロージャ）で宣言された変数を暗黙的に内側の関数に取り込んで操作することができる。主な利点としてはグローバル変数の削減やコールバック関数記述の簡素化が挙げられる。
典型的にはクロージャは、エンクロージャの内側の関数リテラルや、ネストした関数定義によって必要になる。プログラミング言語により、そのような内側の関数内に出現する自由変数（内側の関数の仮引数でもなく、内側の関数自身のローカル変数でもない変数）の扱いは異なるが、自由変数をレキシカルに（字句的に）参照するのがクロージャである。エンクロージャが実行された際、クロージャが形成される。クロージャは内部の関数のコードとエンクロージャのスコープ内の必要なすべての変数への参照からなる。
クロージャはプログラム内で環境を共有するための仕組みである。レキシカル変数はグローバルな名前空間を占有しないという点でグローバル変数とは異なっている。またオブジェクト指向プログラミングにおけるオブジェクトのインスタンス変数とは、オブジェクトのインスタンスではなく関数の呼び出しに束縛されているという点で異なる。
クロージャは関数型言語では遅延評価やカプセル化のために、また高階関数の引数として広く用いられる。
例： クロージャを使ったカウンタの例を Scheme で示す。
 (let ((count 0))
 (lambda ()
 (set! count (+ count 1))
 count)))
(display (c)) ; 1
(display (c)) ; 2
(display (c)) ; 3
関数 codice_1 の中でクロージャが使用されている。codice_2 に代入された無名関数は codice_1 内のローカル変数 codice_4 を参照している。codice_2 を呼び出すたびに codice_4 はインクリメントされていく。
クロージャの用途.
クロージャには多くの用途がある。
クロージャを持つプログラミング言語.
Schemeは完全な静的スコープのクロージャを持つ最初の言語として登場した。Common Lispはそれを取り入れた。実質的にすべての関数型言語（Scala、Haskell、OCamlなど）とSmalltalkに由来するオブジェクト指向言語は何らかの形でクロージャを持っている。
クラスを使用するオブジェクト指向言語では、完全なクロージャになるにはメソッドの中でクラス定義できることが必要だが、メソッドあるいは関数の中でラムダ式／無名関数が使え、その中から外のローカル変数を読み書きできれば、一般的にはそのプログラミング言語はクロージャを使えるとみなされる。よって、クロージャを持つ言語には、C#（3.0以降）、C++（C++11以降）、ECMAScript（JavaScriptを含む）、Groovy、Java（8以降）、Perl、Python、Ruby、PHP（5.3以降）、Lua、Squirrelなどがある。
セマンティクスはそれぞれ大きく異なっているが、多くの現代的な汎用のプログラミング言語は静的スコープとクロージャのいくつかのバリエーションを持っている。
セマンティクスの違い.
言語ごとにスコープのセマンティクスが異なるように、クロージャの定義も異なっている。汎用的な定義では、クロージャが捕捉する「環境」とは、あるスコープのすべての変数の束縛の集合である。しかし、この変数の束縛というものの意味も言語ごとに異なっている。命令型言語では、変数は値を格納するためのメモリ中の位置と束縛される。この束縛は変化せず、束縛された位置にある値が変化する。クロージャは束縛を捕捉しているので、そのような言語での変数への操作は、それがクロージャからであってもなくとも、同一のメモリ領域に対して実行される。例として、ECMAScriptを取り上げると
var f, g;
function foo()
 var x = 0;
 f = function() { x += 1; return x; };
 g = function() { x -= 1; return x; };
 x = 1;
 console.log(f()); // "2"
foo();
console.log(g()); // "1"
console.log(f()); // "2"
関数 codice_7 と2つのクロージャがローカル変数 codice_8 に束縛された同一のメモリ領域を使用していることに注意。
一方、多くの関数型言語、例えばML、は変数を直接、値に束縛する。この場合、一度束縛された変数の値を変える方法はないので、クロージャ間で状態を共有する必要はない。単に同じ値を使うだけである。
さらに、Haskellなど、遅延評価を行う関数型言語では、変数は将来の計算結果に束縛される。例を挙げる。
foo x y = let r = x / y
 in (\z -> z + r)
f = foo 1 0
main = do putStr (show (f 123))
codice_9 は計算 codice_10 に束縛されており、この場合は0による除算である。しかしながら、クロージャが参照しているのはその値ではなく計算であるので、エラーはクロージャが実行され、実際にその束縛を使おうと試みたときに現れる。
さらなる違いは静的スコープである制御構文、C言語風の言語における codice_11・codice_12・codice_13 などにおいて現れる。ECMAScriptなどの言語では、これらはクロージャ毎に束縛され、構文上の束縛を隠蔽する。つまり、クロージャ内からの codice_11 はクロージャを呼び出したコードに制御を渡す。しかしSmalltalkでは、このような動作はトップレベルでしか起こらず、クロージャに捕捉される。例を示して、この違いを明らかにする。
"Smalltalk"
foo
 | xs |
 xs := #(1 2 3 4).
 xs do: [:x | ^x].
 ^0
bar
 Transcript show: (self foo) "prints 1"
// ECMAScript
function foo() {
 var xs = new Array(1, 2, 3, 4);
 xs.forEach(function(x) { return x; });
 return 0;
print(foo()); // prints 0
Smalltalkにおける codice_15 はECMAScriptにおける codice_11 にあたるものだと頭に入れれば、一目見た限りではどちらのコードも同じことをするように見える。違いは、ECMAScriptの例では codice_11 はクロージャを抜けるが関数 codice_7 は抜けず、Smalltalkの例では codice_15 はクロージャだけではなくメソッド codice_7 をも抜ける、という点である。後者の特徴はより高い表現力をもたらす。Smalltalkの codice_21 は通常のメソッドであり、自然に制御構文が定義できている。一方、ECMAScriptでは codice_11 の意味が変わってしまうので、同じ目的には codice_23 という新しい構文を導入しなければならない。
しかし、スコープを越えて生存する継続には問題もある。
foo
 ^[ x: | ^x ]
bar
 | f |
 f := self foo.
 f value: 123 "error!"
上の例でメソッド codice_7 が返すブロックが実行されたとき、codice_7 から値を返そうとする。しかし、codice_7 の呼び出しは既に完了しているので、この操作はエラーとなる。
Ruby.
Rubyなどの言語では、プログラマが codice_11 の振る舞いを選ぶことができる。
def foo
 f.call # control leaves foo here
 return "return from foo"
end
def bar
 f.call # control does not leave bar here
 return "return from bar"
end
puts foo # prints "return from foo from inside proc"
puts bar # prints "return from bar"
この例の codice_28 と codice_29 はどちらもクロージャを作るための方法である。しかし、それぞれが作ったクロージャの codice_11 の振る舞いに関しては、異なるセマンティクスを持っている。
Common Lisp.
Common Lispでは、変数束縛を確立するlet、脱出点を確立するblock、Go Toのタグ(ラベル)を確立するtagbodyの三つの要素を基盤とし、これらの三つの組み合わせによって基本的な構文体系が構築されているが、それぞれの構文で確立された要素は、スコープとエクステント(存続期間)という概念によって整理されている。
これら、三つの構文の、変数名、ブロック名、ラベル名は、レキシカルスコープであり、クロージャに閉じ込めることができるが、変数束縛以外は、スコープ外(エクステント外)からアクセスすることはできない。Common Lispでは、これをレキシカルスコープかつ動的エクステントと表現する(変数はレキシカルスコープかつ無限エクステント)
blockにより確立された脱出点からは、return-fromによって抜け出す。また、tagbodyによって確立されたタグは、goにより参照される。
 (defun a (x)
 ;; 関数定義は暗黙にblock名として関数名を設定する
 (* 3 
 (block b
 (* 100
 (funcall
 (lambda (y)
 (block nil
 (tagbody
 (cond
 ((= 0 (mod y m)) (return-from a y)) ;mの倍数にはaから値をそのまま返す(m=3)
 ((oddp y) (return-from b (* 2 y))) ;奇数には二倍してbから脱出
 (T (go exit))) ;どちらでもなければexitへgo toする
 ;;return-from nilの略記としてreturnが利用可能
 exit (return y)))) ;lambda直下のblock nilから脱出
 x))))))
(let ((m 6)) 
 ;;aの内部で参照するmは定義時のm
 (a 3))
C++.
C++11規格以降でラムダ式が使えるようになった。なお、以下のようにローカル変数のキャプチャの方法を制御することができる。詳細はC++11を参照。
void foo(std::string s) {
 int n = 0;
 // すべての自由変数をコピーキャプチャ。
 auto func1 = [=]() { std::cout « n « ", " « s « std::endl; };
 n = 1;
 s = "";
 func1();
 // すべての自由変数を参照キャプチャ。
 auto func2 = [&]() { n = -1; s = "hoge"; };
 func2();
 std::cout « n « ", " « s « std::endl;
bool findName(const std::vector<std::string>& v, const std::string& name) {
 // 名前を指定して自由変数を参照キャプチャ。
 auto it = std::find_if(v.begin(), v.end(), [&name](const std::string& s) { return s == name; });
 return it != v.end();
クロージャに類似した言語機能.
C.
C言語では、コールバックをサポートするライブラリ関数の中に、以下のように関数へのポインタと付随する任意のデータを指すためのポインタ（例えば汎用ポインタであるcodice_31など）という2つの値を受け取るものがある。
typedef int CallbackFunctionType(void* userData);
extern int callUserFunction(CallbackFunctionType* callbackFunction, void* userData);
ライブラリ関数codice_32がコールバック関数codice_33を実行するたび、実行コンテキストとしてデータポインタcodice_34を使用する。これによってコールバックは状態を管理することができ、登録した任意の情報を参照できる。このイディオムはクロージャと機能面で似ているが、構文面では似ていない。
C++.
C++では、codice_35 をオーバーロードしたクラス（あるいは構造体）により、関数オブジェクトを定義できる。これは関数型言語における関数にいくらか似た振る舞いをみせる。C++の関数オブジェクトは非静的メンバー変数により状態を持つこともできる。しかし、一般的なクロージャのように自動的に（暗黙的に）ローカル変数を捕捉（キャプチャ）するようなことはしない。
また、ローカルクラス、すなわち関数内でクラスを定義することも可能だが、C++11よりも前の規格（C++03以前）ではテンプレート型引数として渡すことができなかったり、暗黙的に参照できる外のローカル変数は static 変数のみであり、自由変数のキャプチャを模倣するためには関数オブジェクトの非静的メンバー変数として明示的に保存しておく必要があったりするなど、後述する Java の無名クラス以上に制約条件が多い。C++11以降のラムダ式は、内部的にはコンパイラによる関数オブジェクトの自動生成により実現されている。したがって、自由変数をキャプチャする際には、関数オブジェクトであってもラムダ式であっても、変数寿命に配慮する必要がある。
Eiffel.
Eiffelにはクロージャを定義するためのinline agent（インラインエージェント）がある。インラインエージェントはルーチンを表すオブジェクトで、次のように利用する。
OK_button.click_event.subscribe(
 agent(x, y: INTEGER) do
 country := map.country_at_coordinates(x, y)
 country.display
 end
codice_36 の実引数はインラインエージェントで、2つの引数を持つ手続きである。ユーザがこのボタンをクリックして、codice_37 タイプのイベントが起こると、マウスの座標を引数としてこの手続きが実行される。
Eiffelのインラインエージェントの大きな限界は、外側のスコープのローカル変数を参照できないという点である。
Java 7 以前.
Java 7 以前では、メソッド内部に「ローカルクラス」あるいは「匿名クラス」を定義することで似たようなことができる。ローカルクラス／匿名クラスからは、そのメソッドの codice_38 （リードオンリー）なローカル変数を、ローカルクラス／匿名クラスのフィールドと名前が衝突しない限り、参照できる。
class CalculationWindow extends JFrame {
 private JButton saveButton;
 public final void calculateInSeparateThread(final URI uri) {
 // The expression "new Runnable() { ... }" is an anonymous class.
 Runnable runner = new Runnable() {
 void run() {
 // It can access final local variables:
 calculate(uri);
 // It can access private fields of the enclosing class:
 // Always update the Graphic components into the Swing Thread
 SwingUtilities.invokeLater(new Runnable() {
 public void run() {
 saveButton.setEnabled(true);
 }); 
 };
 new Thread(runner).start();
要素が1つの配列を codice_38 な参照で保持すれば、クロージャで1つのローカル変数を参照する機能をエミュレートできる。内部クラスはその参照の値そのものを変えることはできないが、参照されている配列の要素の値は変えることができるからである。このテクニックはJavaに限ったものではなく、Pythonなど似た制限を持つ言語でも有効である。
Javaに完全なクロージャを追加するという言語拡張が検討されていた。様々な問題により、クロージャを導入せずに、関数型インタフェースを実装するための簡便な表記法（ラムダ式）が Java 8 にて導入された。
実装.
クロージャは典型的には関数コードへのポインタ及び関数の作成時の環境の表現（例えば、使用可能な変数とその値の集合など）を含む特別なデータ構造によって実装される。
ある言語処理系の実行時のメモリモデルがすべてのローカル変数を線形なスタックに確保するものであれば、クロージャを完璧に実装するのは容易ではない。それは、以下のような理由による。
第1の問題を解決するために、クロージャを実装するプログラミング言語は大抵、ガベージコレクションを備えている。この場合、クロージャへの参照が全て無効になった時に、レキシカル変数はガベージコレクタに渡される。
第2の問題を解決するためには、デリゲートのように、関数の参照と実行環境の参照をセットで扱える必要がある。しかし、これではC言語のようなネイティブコードの関数の呼び出しとの互換性がなくなる。そのため、実行時にスタックやヒープに、エンクロージャのスタックポインタを埋め込んだ、実際の関数を起動するだけの小さな関数（トランポリン関数）を動的に生成することでも実装できる。しかし、セキュリティの観点から近代的なOSでは標準でスタックやヒープ上のコードの実行を禁止しているのが一般的であり、この制限を一時的・部分的に解除することをサポートしている環境でなければ実現できない。
現代的なScheme処理系は、クロージャに使用される可能性のあるローカル変数は動的に確保し、そうでないものはスタックに確保するなどの最適化を行うものが多い。