クロージャとは コンピュータの人気・最新記事を集めました - はてな (original) (raw)

クロージャ

【closure】閉包。レキシカルクロージャとも言う。
静的スコープ(レキシカルスコープ)を実現するために必要となる。
関数内に出現する自由変数(関数内で宣言されていない変数)の解決の際、実行時の環境ではなく、関数を定義した環境の変数を参照できるようなデータ構造。

「推移的閉包【transitive closure】」とかのクロージャとは全く関係がないのに同じ名前なことが、言語を越えて学習者を無意味に悩ませている

以下のようなコードを考える(文法はJavaScript)

function makeCounter () { var count = 0; return f;

function f () { return count++; } }

var count = 10; var counter = makeCounter(); document.writeln(counter()); document.writeln(counter()); document.writeln(counter()); document.writeln(counter());

クロージャである(静的スコープ)とき、出力はこのようになる。

0 1 2 3

クロージャでない(動的スコープ)とき、出力はこのようになる。

10 11 12 13

Lisp

Lispでは、方言によってクロージャを提供するかに違いがある。
Lispは、歴史的には動的スコープであり、Emacs Lispは動的スコープである。
Schemeは、クロージャ(静的スコープ)を採用した最初のLisp方言である。
Common Lispは、クロージャ(静的スコープ)を採用しているが、スペシャル変数によって動的スコープを利用する事もできる。

Emacs Lispでは、次のコードは、

(let ((count 0)) (defun get-count () (setq count (+ count 1)) count) (let ((count 10)) (print (get-count)) (print (get-count)) (print (get-count)) (print (get-count))))

このように出力される。

11 12 13 14

それに対し、等価な、次のSchemeのコードは、

(let ((count 0)) (define (get-count) (set! count (+ count 1)) count) (let ((count 10)) (print (get-count)) (print (get-count)) (print (get-count)) (print (get-count))))

このように出力される。

1 2 3 4

その他

誰かが言っていたが、クロージャは並大抵の苦労じゃ実装できないらしい。

このタグの解説についてこの解説文は、すでに終了したサービス「はてなキーワード」内で有志のユーザーが作成・編集した内容に基づいています。その正確性や網羅性をはてなが保証するものではありません。問題のある記述を発見した場合には、お問い合わせフォームよりご連絡ください。