クロージャについて、どんどん発散して行くなあ。

色々考えていることを整理してみたいと思ったのですが、意に反して、どんどん発散してしまいます。こんなときはまだ整理できる段階ではないということで、発散するままに書き連ねてしまうことにしてみました。

先のエントリで少し触れましたが、私は、クロージャの本質を「状態の保持」と捉えています。
この「状態」とは、Scheme 的に言えば、`環境' と言うことになりましょうか。

スコープ

そう言う意味では、自由変数へのアクセスをクロージャの定義 (生成) 時点のスコープで行なうのか、動作 (評価) 時点のスコープで行うのかという話については、枝葉でしかないのでは、と思っています。
いえ、自由変数へのアクセスがクロージャの定義 (生成) 時点のスコープで行なわれることには大きな意味があるのですが、それは「定義時点のものか、動作 (評価) 時点のものか」という視点で考えるものではなく、「一つの環境に特定できるかどうか」という視点で考えるべきものじゃないのだろうかと思うのです。

つまり、ダイナミックスコープな環境でクロージャが生成できないのは、クロージャが評価される文脈で、クロージャから見える環境が異なってしまうことに問題があるからだと思う訳です。
逆を言えば、ダイナミックスコープであっても、生成されたクロージャが存在している間、特定の環境にのみ結び付けられる仕組みがありさえすれば良いと言えるのかもしれません。

また、コードブロックの上位階層に遡って自由変数にアクセスすることについても、必ずしも必要なものではないのでは? とも思っています。そう考えると、自由変数は抜きにして、束縛変数だけで環境を構成するというのもアリかと思いました。クロージャの作り易さという面をスポイルすることにはなってしまうかもしれませんが。

オブジェクトとの類似

この、状態 (環境) の保持という面では、`継続' も同じかと思っています。しかし、継続の場合は、その目的、役割がプログラムの実行制御 (状態遷移と言った方が良いのかな) のためのものであり、クロージャとは異なってくるのでしょう。
あ、クロージャも、コールバック手続きとして使われる様なケースでは、継続と似た役割を持つことになると言えるのかもしれませんが。

そして、状態 (環境) の保持が本質であると考えると、やはりオブジェクト指向で言うところのオブジェクトやインスタンスの単純な一形態と言えるのではないかと思うのです。
インスタンスごとに状態 (環境) として変数群を保持し、それらに作用する、或いはそれらに基く処理を行なう手続きを持つ、立派なオブジェクトと言えると思います。
内部状態となる変数に手続きを保持して適用することも可能な訳ですから、インスタンスごとに手続き自体の振る舞いを変えることも可能ですね。
クロージャ自身は一つの手続きとなるため、メソッドを複数持てるオブジェクトに比べて貧弱に思われるかもしれませんが、同じ状態 (環境) に対して複数のクロージャを生成することができるので、複数のメソッドを持つオブジェクトと同等の振る舞いを持たせることも可能ですし。複数クロージャの管理には工夫が必要になるでしょうが。

所謂オブジェクト指向言語による様々なサポートを全て実現できるというつもりはありません (工夫すれば何とかなるでしょうが、その工夫のコストを掛けることが妥当でないという判断はありでしょう) が、仰々しいオブジェクト設計とは別に、ある局面でのみ簡単に独立したオブジェクトを導入したい、といったときには十分に有効かと思います。

ブロックとの違い

コレクション操作、イテレータなどの高階関数クロージャを渡すときには、状態の保持が必要ない場合もありますね。個人的には、この様なケースではクロージャではなく単なるブロックと考えているのですが、特に区別する必要は無いのでしょうね。
高階関数に渡すときでも、状態の保持が必要な場合も当然あって (コレクションの要素を数え上げるとか)、その様な場合にはクロージャ、そうでないときはブロックと区別することに意味は余り無いでしょうし、実装での区別も無いでしょうから。
Ruby だとブロックを渡すときと Proc オブジェクトを渡すときで違うと言えるのかなあ。