langsmith:150
From: W <ttn3w7u2fs mx6.ttcn.ne.jp>
Date: Mon, 11 Oct 2004 00:16:11 +0900
Subject: [langsmith:150] Re: 例外処理:Eiffel とRuby
皆さん、情報ありがとうございます。 1) 2点、勉強になりました: 1-1) 例外処理って多様なんですね。Eiffel 以降、例外処理は DbC が標準だと 勝手に思いこんでいたのが間違いだったのがよく分かりました(苦笑)。 1-2) OOSC には、普通のステータスチェック方式( if status then ...)の方が 例外ハンドラ方式(exception, rescue, catchなど)より優れているケースを論じ ていたので、てっきり Eiffel の例外処理は両者を統合したものかと理解してい ましたが、まつもとさんの指摘により、それも私の勘違いだったようです(OOSC を読み返してみると、確かにそうでした)。つまり、Eiffel では契約による例 外処理だけを例外処理としており、それ以外は普通方式の2本立てだったと。 2) まつもとさんの指摘「DbC だとイベントループでファイルがオープンできな かった場合に対処できないのでは」に関しては、対応策が見つかりましたのでこ こに書きます: 2-1) イベントループの上位で補足する方法 -- ニセ Eiffel do loop event.get event.dispatch --file open 含む end rescue if exception = file_open_error then retry end -- 捕捉出来ないエラーは異常終了 end 2-2) 原始的方法(OOSC1 邦訳 p.210 的方法) wrapped_file_open(filename : STRING) is local open_tried : BOOLEAN --default値 false に初期化 do if not open_tried then file_open(filename) end rescue open_tried := true; retry end うーむ、美しくない。しかし、これが教科書(OOSC)にも載っているやり方だ。 2-3) EXCEPTIONS クラスを継承し、その ignore フィーチャを使用する。 多分、これがまつもとさんに対する Eiffel の標準の回答かも。 3) NetNews の comp.lang.eiffel に、10年前の議論ですが Meyer 自身が「なぜ rescue句を ブロック単位には書けずルーチン(手続き・関数)にしか書けないのか」に回答 していました (半日かけて探しました。暇だな私も): > The unit of computation in Eiffel, and I believe > in the O-O method, is the routine (more generally the feature). Only a > routine has a precondition and a postcondition - a contract - allowing > the software reader to reason formally or semi-formally about it. > If an operation has non-trivial semantics, as is inevitably the > case if it must include exception handling, then it is appropriate > to encapsulate it into a routine. ( http://groups.google.co.jp/groups?hl=ja&lr=&selm=161%40glasgow.eiffel.com ) 要約すると「OO における処理の単位はルーチンであり、ルーチンのみが事前条 件と事後条件 --即ち契約-- を供えている。もし処理が単純でないなら、つまり、例外を伴う なら、それを ルーチンにカプセル化するのが適切だ」ということらしいです。 確かに、事前条件・事後条件をルーチンにしか書けないなら、例外処理もルーチ ンにしかかけないのが 設計の一貫性なのかも、という気もしないでもないです。 しかし、例外処理をエラー処理に一般化するなら(Eiffelは違うのですが)、従 来の例外機構を持たない言語で は普通のエラーステータスチェックが1行1行の文の単位で起こりうることを考 えると、ちょっと違うのでは、と 私には思えます。 4) この話(↓)に戻らせてください: 1) エラーコード(やメッセージやエラーオブジェクト)を伴うか否か 2) rescue句(Java/C++系 では catch ブロック)の最後で呼び出し側に伝搬するか否か 3) retryできるか否か 4) 任意の文やブロックで rescue句(Java/C++系 try-catch)が書けるか (5 は話しがずれそうなので止めます) 2) ですが、comp.lang.eiffel にも投稿されていましたが、C++系とEiffel系はお互い他者を シミュレートすることはできるようです。なので、default の動作がどうか、という議論になるかと 思いました(C の switch文と Pascalの case文が、デフォルトで fall through かどうか、という 議論と同様ですね)。つまり、Eiffel で C++系をシミュレートするには rescue エラー処理プログラム ignore -- EXCEPTIONS クラスのルーチン end C++系で Eiffel をシミュレートするには catch { エラー処理プログラム throw } ということでしょうか。 ここからは私見ですが、デフォルトの動作としては Eiffel的なほうが私としては好ましかと思っています。 (他の例でいうなら、make vs shell でしょうか。shell では A B とあった場合、A でエラーが発生しても B の処理に続きますが、make では A でエラーになると そこで止まる。無視したい場合は前に '-' を明示的に付けないといけない、という。) さて、最後に、ここら辺(ブロックごとの rescue, 例外処理の default は例外の上位への伝播を伴う) を取り入れた言語とは、果たして使えるのか?というところが一番の私の関心ごとでして。 作ってみるしかないのかな。 // W -- ML: langsmith quickml.atdot.net 使い方: http://www.atdot.net/~ko1/quickml
135 2004-10-07 00:06 [ttn3w7u2fs mx6.ttcn.] 例外処理:Eiffel とRuby 136 2004-10-07 00:41 ┗[matz ruby-lang.org ] 138 2004-10-07 11:29 ┗[ttn3w7u2fs mx6.ttcn.] 139 2004-10-07 12:35 ┣[matz ruby-lang.org ] 144 2004-10-07 21:49 ┃┗[randy mvd.biglobe.ne] 145 2004-10-07 22:04 ┃ ┗[matz ruby-lang.org ] 146 2004-10-08 21:59 ┃ ┗[randy mvd.biglobe.ne] -> 150 2004-10-11 00:16 ┃ ┗[ttn3w7u2fs mx6.ttcn.] 151 2004-10-11 00:52 ┃ ┗[matz ruby-lang.org ] 154 2004-10-13 00:00 ┃ ┗[ttn3w7u2fs mx6.ttcn.] 155 2004-10-13 01:30 ┃ ┗[matz ruby-lang.org ] 140 2004-10-07 14:23 ┣[takehiko eel.rdc.tos] 141 2004-10-07 14:33 ┃┗[matz ruby-lang.org ] 143 2004-10-07 16:50 ┃ ┗[takehiko eel.rdc.tos] 142 2004-10-07 15:20 ┣[shiro lava.net ] 156 2004-10-14 12:32 ┃┗[maeda-langsmith atus] 147 2004-10-08 22:21 ┗[ko1 atdot.net ] 148 2004-10-09 06:42 ┗[shiro lava.net ]