From: matz@... (Yukihiro Matsumoto) Date: 1996-08-08T13:08:34+09:00 Subject: [ruby-list:385] about exception まつもと ゆきひろです. 例外の話が出ましたので,もうちょっと詳しい話をしましょう. # そもそも例外とはなんだと思っている方もいらっしゃるかも知れ # ませんが,これについては後で(いつか)説明しましょう. 1. system callから発生する例外 rubyはsystem callが負の値を返すと例外を発生するようになっ ています.この時の $! の値は perror() の出力する文字列と同 じです.つまり,perror() で出力される文字列です. これらはrubyのドキュメントには載っていませんが(いつか載せ ます),を見ると載っています. 2.なぜrubyの例外処理はああなのか 一応いろいろ考えた結果ああなっているわけです.ここで説明し ましょう. 例外が発生した時にその対応としては以下のような場合が考えら れます. (1) その場でプログラムを中断する (2) 例外の種類にかかわらず,なんらかの対応を行う (3) 例外の種類毎に,それぞれ別の対応を行う 1の場合にはrubyの場合何もする必要はありません.勝手にエラー メッセージを出してプログラムを中断してくれます. 2の場合,現在のrescueの仕様でなんの問題もありません. 3の場合は変数 $! に例外情報が文字列で入っているので,それ によって分岐する必要があります.また例外の種別以外に何らか の情報が必要であれば,大域変数などを使ってなんとかして情報 を渡す必要があります. 今,話題に登っているのは,3の場合にいろいろと面倒だ,と言 うものです(よね). でも,私の経験からは普通にrubyを使っている場合,ほとんどの ケースは1または2で対応できてしまうので,3のケースはそれほ ど多くない気がしています. 実際,私の書いたかなりのコードではrescueよりもensureの方が 多用されていますし,rescueを使ってもそのあと例外の種類に応 じて分岐することが必要だったことはそれほどありませんでした. 言い替えると私の書いた例外処理のほとんどは「xxxという処理 が行われなかったことに対応する」コードまたは「例外が起きて もyyyという処理が行われることを保証する」コードで,「xxxと いう処理がzzzという原因でできなかったことに対応する」コー ドでは無かったようです. 一例をあげると「サーバがクライアントの処理中に例外を発生さ せたので,クライアントのソケットをクローズする」ような場合 があるでしょう.この時の例外の原因は,クライアントが落ちた のでも,クライアントが間違ったプロトコルで通信したのでも, サーバプログラムのバグでもなんでも結局は同じことです.エラー ログには $! の値を出力しておけばデバッグ用の情報もばっちり です. いや,もちろん厳密には例外の原因によっていろいろできるので しょうけど,大体の場合にはこれで実用上十分だと思います. というわけで,*私は*例外処理には1,2のケースが十分多く,3 はむしろまれなケースであると認識しています(勝手な認識では ありますが).もっとも私の限られた経験からでは断言はできま せんけど. 一応,傍証をあげれば,IconとEiffelの例があります. Iconという言語には例外(というか失敗)があって,これには種類 の情報が全くついていません.ただ失敗するだけです.でもちゃ んと使えるようです.Iconの場合には徹底していて,失敗が偽で それ以外の値が全て真になっています. Eiffelという言語はなかなか大胆な部分で機能を切り落としてい る言語なんですけど(例えば大域変数だとか,クラス変数だとか が無い),この言語にも例外に種類の情報がついていません. rescueという単語から,rubyへのEiffelの影響を見抜いた人は鋭 すぎます. rubyの例外も「例外が発生した」というのがメインで,例外の種 別の情報($!)はむしろ付加的な情報であるような気がします. 3.歴史の時間 そもそもrubyの開発に取り掛かる前から,次に設計する言語には 例外をつけようと思っていました.むかしBitという雑誌にCLUと いう言語に関する連載がありまして,それの影響を受けたのが直 接の原因です. で,rubyを設計していた時のメモを引っ張りだしてみると,4種 類の例外案が載っています(3年前の5月のものです). * Icon式例外(失敗が偽) * 単純型(今のrubyのもの) * 名前つき例外 * 名前つき値あり例外(CLU式) んで,結局上で述べたように,rubyの対象とする領域では個々の 例外を区別する必要はそれほど無くて,例外処理機能は単純なも ので良いだろうとの結論を出したわけです.その決断が正しかっ たかどうかはまだ結論は出ていないようですが,個人的にはCLU 式の例外処理(今はC++やJavaもこのタイプの例外機能を持ってい ますね)よりも「お手軽」で良いと思っています. # この時のメモは結構面白くて,rubyの仕様がまだ固まっていない # 時の迷いが感じられますし,今ある機能がどういう過程で決まっ # て行ったのかが良く分かります.またいつか紹介しましょう. というようなわけで,私はrubyの例外機能はあのままで良くて,た だドキュメントには(いつか)メソッドが発生させうる例外をきちん と明示した方が良いと思うのです.少なくとも,あるメソッドが例 外を発生させうるかどうかという情報は必須ですね.今はそれさえ ないものがあるので. まつもと ゆきひろ /:|)