クロージャ

(コンピュータ)
くろーじゃ

【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

その他

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

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

ネットで話題

もっと見る

関連ブログ