[#380] bug report#3 and request#5 — keiju@... (Keiju ISHITSUKA)
けいじゅ@SHLジャパンです.
1 message
1996/08/06
[ruby-list:385] about exception
From:
matz@... (Yukihiro Matsumoto)
Date:
1996-08-08 04:08:34 UTC
List:
ruby-list #385
まつもと ゆきひろです.
例外の話が出ましたので,もうちょっと詳しい話をしましょう.
# そもそも例外とはなんだと思っている方もいらっしゃるかも知れ
# ませんが,これについては後で(いつか)説明しましょう.
1. system callから発生する例外
rubyはsystem callが負の値を返すと例外を発生するようになっ
ています.この時の $! の値は perror() の出力する文字列と同
じです.つまり,perror() で出力される文字列です.
これらはrubyのドキュメントには載っていませんが(いつか載せ
ます),<errno.h>を見ると載っています.
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の例外機能はあのままで良くて,た
だドキュメントには(いつか)メソッドが発生させうる例外をきちん
と明示した方が良いと思うのです.少なくとも,あるメソッドが例
外を発生させうるかどうかという情報は必須ですね.今はそれさえ
ないものがあるので.
まつもと ゆきひろ /:|)