クロージャ

http://www.torus.jp/memo/x200406/flash_closure.rd.html
http://namazu.org/~satoru/blog/archives/000040.html
http://kmaebashi.com/programmer/devlang/object.html
無名関数とそれを包み込む無名パッケージをセットでクロージャと呼ぶ。
一番簡単な使い方としては

a = function(){
  print "hello.closure.";
}

a();

というもので、扱いやすい関数ポインタと同じだと考えればよい。
イベントハンドラに、その関数を代入するというような使い方をするようだ。
しかし、単なる関数ポインタとの大きな違いが、無名関数内から無名関数の外のブロックの変数を、グローバル変数であるように参照できる、というところである。
さらには、クロージャ内にクロージャを作ることで、オブジェクトで実装するより直接的にある範囲内からしか参照できないグローバル変数、つまり「去勢されたグローバル変数」を作ることができる。

a = function(){
       var closure_global = 0; //この変数は、変数aから参照されているクロージャ全体が開放されない限り存在し続ける。
       return function() {
           print closure_global++;
       }
    };

a(); //1が表示される
a(); //2が表示される
a(); //3が表示される

考え方としては、クロージャは「定義元関数へのポインタ」を保持している。と考えると良いかもしれない。
呼び出し元関数の変数スコープは、クロージャから参照されているので、そのクロージャを開放するまで消えないというわけだ。
(暗黙のうちにガベージコレクタで変数開放することになっているが、気にするな)ちなみに、クロージャAの定義元がクロージャBだと、クロージャA内では、クロージャBとクロージャBの「定義元関数へのポインタ」がグローバル変数のように使える。
つまり、クロージャA→ポインタで、クロージャBを参照。加えてクロージャBから→定義元関数へのポインタを参照。
と、やっているのだと思う。

a = function () { var closure_a = "a"; 
      function () { var closure_b = "b";
        function () { print closure_a + "," + closure_b; }
      }
    };
a(); // a,bと表示される。

これを「スコープチェーン」と呼ぶらしい。うわっ、カッコイイぜ。

                                                        • -

ちなみに、クロージャというのは、もともとは関数型言語の概念らしい。
このクロージャに限らず、関数型言語は常に一回点半ひねりを加えた次世代言語構造を実装しいるという気がする。

  • meta: closure スコープチェイン ScopeChain