Rubyの力はブロックにありと常々主張している。その文脈導入の力。そして、それを陰から支えるのが継続である。
Rubyの力はブロック構文にある。これを単なるlabmdaだとかコールバックだとか言ってしまうのは簡単だが、こういう構文の形をしていることに意味がある。まつもとさんは IPA未踏 千葉滋PM案件報告会 において、「DSLにおいてコンテキストを生成する」という点に着目してこれを説明した。例えば、Rakefileにおけるターゲットがそうであるし、Railsのconfig/routes.rbがそうである。
まつもとさんの言う視覚的に明確な形でコンテキストを導入する力としてのブロックに含まれてしまうのだが、私が常々主張してきたのは File.open
のようなリソース管理の方法としてのブロックである。
先日ついつい 愚痴 を書いてしまったけれど、GCな世界で育った初心者はどうもリソース管理の意識が甘い気がする。メモリーという一番目に付くリソースを管理しなくても済んでしまうがために、リソースを解放することについての執念深さが身につかないのだ。でも、それは「近頃の若い人」が悪いのでは無い。言語が悪いのだ。リソースをオブジェクトに結びつけて扱うなら、オブジェクトが解放されるときにリソースも解放されるべきだ。言語ライブラリの実装が変なのである。ファイナライザの実行は保証されないとか言われても困る。
リソースを管理する力と言う点については、「Java <<<(越えられない壁)<<< C++」と思っている。オブジェクト破棄の権限(delete)をユーザーから奪うなら、結び付いたリソースの後始末についても処理系やライブラリが責任を持つべきだ。
.NETの IDisposable
というのは1つの解決だけれども、Rubyの File.open
の存在は、コードにコンテキストを導入する一般的な構文があればリソース管理の特別な構文なんか必要ないことを示している。これが、Rubyの力だ。ブロックつきの File.open
を使わせておけば、最早初心者のリソースリークは心配しなくていい。プログラマのミスを心配しなくていい。ブロックを抜けたら勝手にファイルはcloseされる。DBのトランザクション然り、外部システムへのコネクション然り。
そして、これを陰から支えるのが継続だ。 継続は力なり 。ブロックを抜けて勝手に解放されるのはいいのだけれど、構文上のスコープがプログラムの実行パスと完全には一致しなかったらどうするか。そこは継続でなんとかするのである。最近、 ActiveRecord::ConnectionAdapters::DatabaseStatements.transaction
とかで重宝した。まつもとさん作の「 既存の CGI をそのまま FastCGI 対応に 」あたりは好例だろう。
Rubyが単なるLispのALGOL化(そして再帰的記述能力の喪失)でないのは、PerlのOO化(そして簡潔さの喪失)でないのは、ブロック構文があるからである。ブロックが力なのである。