クロージャ
コンピュータサイエンスでは、クロージャーとは、それ自体が環境を持つ関数のことです。この環境には、少なくとも1つのバインド変数(数値などの値を持つ名前)があります。クロージャの環境は、クロージャが使用されるまでの間、束縛変数をメモリ内に保持します。
Peter J. Landinは1964年にこのアイデアにクロージャという名前をつけた。クロージャが普及したのは、1975年以降のプログラミング言語「Scheme」です。それ以降に作られた多くのプログラミング言語にもクロージャが搭載されている。
匿名関数(名前のない関数)は、間違ってクロージャと呼ばれることがある。無名関数を持つほとんどの言語にはクロージャもある。無名関数は、少なくとも1つの束縛された変数を持つ自分自身の環境を持っていれば、クロージャでもある。自身の環境を持たない無名関数はクロージャではない。名前付きクロージャは匿名ではない。
クロージャとファーストクラスの関数
値には、数字や文字などの他の種類のデータや、より単純なパーツで構成されたデータ構造などがあります。プログラミング言語のルールでは、関数に与えることができる値、関数が返すことができる値、変数名に束縛される値を第一級の値としている。また、他の関数を受け取ったり返したりする関数を高次関数と呼ぶ。関数を一級値とする言語の多くは、高階の関数やクロージャも持っている。
例えば、次のようなScheme関数を見てみましょう。
この例では、ラムダ式 (lambda (book) (>= (book-sales book) threshold))
が関数 best-selling-books
の一部となっています。関数が実行されると、Schemeはラムダ式の値を作らなければなりません。これはラムダのコードと、ラムダ内の自由変数であるしきい値
変数への参照を持つクロージャを作ることで行われます。(自由変数とは、値に束縛されていない名前のことです)。
フィルタ
関数は、リストの各ブックに対してクロージャを実行し、返すべきブックを選びます。クロージャ自身がしきい値
への参照を持っているので、filter
がクロージャを実行するたびに、クロージャはその値を使うことができます。filter
関数自体は、全く別のファイルに書くこともできます。
同じ例をECMAScript(JavaScript)で書き直してみました。これはクロージャをサポートするもう一つの人気言語です。
ECMAScriptでは、ここでlambda
の
代わりにfunction
という単語を使い、filter
関数の代わりにArray.filter
メソッドを使っていますが、それ以外は同じことを同じように行っているコードです。
関数は、クロージャを作成してそれを返すことができます。次の例は、関数を返す関数です。
スキームで
ECMAScriptでは
クロージャ環境では、囲み関数(導関数
)が戻った後も、束縛変数f
とdx
が保持されます。クロージャのない言語では、これらの値は囲み関数が戻った後に失われてしまう。クロージャを持つ言語では、どのクロージャでも結合変数を持っている限り、結合変数をメモリに保持しなければならない。
クロージャは、無名関数を使って形成する必要はありません。例えば、Pythonは、無名関数のサポートが限られていますが、クロージャを備えています。例えば、上記のECMAScriptの例をPythonで実装する方法の1つは、次のようになります。
この例では、gradientという関数が、変数fとdxとともにクロージャを作っています。外側にある derivative という関数は、このクロージャを返します。この場合、無名関数でも問題ありません。
Pythonでは、ラムダ式が他の式(値を返すコード)のみを含み、文(効果を持つが値を持たないコード)を含まないため、しばしば名前付き関数を代わりに使用しなければならない。しかし、Schemeのような他の言語では、すべてのコードは値を返しますが、Schemeではすべてが式です。
クロージャの使い方
クロージャーには様々な用途があります。
- ソフトウェアライブラリの設計者は,重要な関数の引数としてクロージャを渡すことで,ユーザが動作をカスタマイズできるようにすることができます.例えば、値をソートする関数は、ユーザが定義した基準に従ってソートされる値を比較するクロージャ引数を受け入れることができます。
- クロージャは評価を遅らせる、つまり呼び出されるまで何もしないので、制御構造の定義に使うことができます。例えば、分岐(if/then/else)やループ(whileやfor)など、Smalltalkの標準的な制御構造はすべて、メソッドがクロージャを受け入れるオブジェクトを使って定義されています。ユーザーが独自の制御構造を定義することも簡単です。
- 同じ環境に閉じた複数の機能を作り、その環境を変えることでプライベートなコミュニケーションを図ることができます(割り当て可能な言語で)。
スキーム内
- クロージャは、オブジェクトシステムの実装にも利用できます。
注:字句環境を束ねるデータ構造をクロージャーと呼ぶ人もいますが、通常は関数に限定して呼ばれます。
質問と回答
Q:コンピュータサイエンスにおけるクロージャとは何ですか?
A: クロージャとは、それ自身の環境を持つ関数のことです。
Q: クロージャの環境は何を含んでいますか?
A:クロージャの環境には、少なくとも1つの境界変数が含まれています。
Q:クロージャの名前をつけたのは誰ですか?
A: 1964年、ピーター・J・ランディンがクロージャのアイデアを命名しました。
Q:1975年以降にクロージャを普及させたプログラミング言語は?
A: 1975年以降、Schemeというプログラミング言語がクロージャを普及させました。
Q: 無名関数とクロージャは同じものですか?
A:無名関数はクロージャと間違って呼ばれることがありますが、すべての無名関数がクロージャというわけではありません。
Q: 無名関数がクロージャである理由は何ですか?
A: 無名関数は、少なくとも1つの束縛された変数を持つそれ自身の環境を持っていれば、クロージャです。
Q: 名前付きクロージャは匿名ですか?
A: いいえ、名前付きクロージャは匿名ではありません。