Dispose の書き方と確定的破棄に関する戦略
現在の C# はこんな感じだけど
void Foo() { using (StreamReader file = new StreamReader(@"C:\a.txt")) { // ファイルを使った処理... } // ここで Dispose }D っぽくこう書けるようにならないかなー
void Foo() { scope StreamReader file = new StreamReader(@"C:\a.txt"); // ファイルを使った処理... } // ここで Disposeそれか Ruby のブロックぽく・・・
void Foo() { new StreamReader(@"C:\a.txt") { |file| // ファイルを使った処理... } // ここで Dispose }んー・・・やっぱり D だな
うちの Achiral なら,こんな感じで書けます.
Console.WriteLine( new StreamReader(@"C:\a.txt").Dispose(file => file.ReadToEnd()) );
あるいはこっちでも.
Make.Repeat(() => new StreamReader(@"C:\a.txt")) .Select(file => file.ReadLine()) .TakeWhile(line => line != null) .ForEach(line => Console.WriteLine(line));
どちらを使っても,確定的破棄は原則的に実現できてます.前者はラムダ式があれば Ruby っぽいことは書けますよというよくある例.後者は確定的破棄は IEnumerator 連鎖の文脈で合成できますよという例.のつもり.
てのはまあどうでもいいんですが.
シンタックスを超えて
『C++ の設計と進化』で印象深かったのがこの点.結局いつもシンタックスの議論で白熱しちゃうんですよね.
でも,どのシンタックスを選んでも,.NET の制限のせいで『using 構文使用時に Dispose が呼出されない確率 - NyaRuRuの日記』の問題は解決できないじゃん,みたいな話は全然盛り上がらないし.
シンタックスを弄るのなら Nemerle や Scala みたいな方向性の言語が向いていると思いますが,単にシンタックス弄っているだけだとやっぱり埋没するんじゃないかという気もします.結局そのシンタックスでどんな戦略を実現するか,が勝負になるのかなと.
追記
『C++ の設計と進化』を読み直してみたら以下の部分が無茶苦茶味わい深かった.流石だ.
3.3 例外安全性
(略)
ここでのキーとなる教訓は、言語特徴がどう振る舞うかを知るだけでは不十分だということだと、私は思う。よいソフトウェアを書くには、その特徴を要求する問題に対して、極めて明晰な設計戦略を持たねばならない。