[ruby-list:242] TUTORIAL - exception handling
From:
matz@... (Yukihiro Matsumoto)
Date:
1996-03-06 08:43:26 UTC
List:
ruby-list #242
まつもと ゆきひろ@トヨタケーラムです.
今回は「例外処理」です.これであともうひとつになりました.
# 例題のプログラムを作らないとな.
--
例外処理
プログラムの動作に例外的な状況はつきものだ.ファイルをオープ
ンしようとすれば,ファイルが存在しないかも知れないし,書き込
もうとすれば,ディスクがいっぱいかも知れない.こういう状況を
考慮していないプログラムは品質が悪いといわれる.
問題は例外的な状況が発生したかどうかが,いちいち「今の処理は
大丈夫でしたか」と確認しなければ分からないことだ.例外的な状
況で処理が正しく行われていないのに続きを実行すれば,当然問題
が起きる.例外的な状況が発生したら,そのまま処理を続けてはい
けないのだ.
rubyではこういう例外的な状況では「例外」が発生する.特になに
も対処しなければ,「例外」はプログラムの実行を中断する.これ
で例外的な状況に対処せずに処理を続けてしまう心配は無い.
ruby> file = open("/file_not_exist")
ERR: No such file or directory - /file_not_exist
Cなどならオープンできたかプログラマがチェックする必要がある
が.rubyでは「例外が発生していないのでちゃんと処理が行われた」
と仮定することができる.Cで書くとこういう風になる.
FILE *file = fopen("/file_not_exist", "r");
if (file == NULL) { /* エラー処理 */ }
エラー処理する必要がない分,プログラムがすっきりするのが分か
るだろう.
先程も説明したように,例外が発生すると,プログラムの実行は中
断される.が,それでは嬉しくないことも多いだろう.例外の原因
に対応してプログラムを継続したい場合もあるはずだ.そういう時
には'begin'を使って,例外を捕捉する必要がある.使い方はこう
だ.
ruby> begin
ruby| file = open("/file_not_exists")
ruby| rescue
ruby| file = STDIN
ruby| end
nil
ruby> print file, "==", STDIN, "\n"
#<IO:0xbff58> == #<IO:0xbff58>
nil
openに失敗したので,fileにSTDINが代入されたのが分かるだろう.
beginは本体を実行している最中に例外が起きるとrescue以下のエ
ラー処理を実行する.
beginには「やり直し」の機能もある.これには`retry'を使う.
rescueの中でretryが使われるとbeginのはじめから実行をやり直す.
これを応用するとこんな感じになる.
ruby> fname = "file_not_exists"
ruby> begin
ruby| file = open(fname)
ruby| # なにか file を使った処理
ruby| rescue
ruby| fname = "file_exists"
ruby| retry
ruby| end
nil
fileのオープンに失敗するとfnameに代わりのファイル名を代入し
てやり直すわけだ.処理の流れは以下のようになる.
* openで例外が発生する
* rescue以下へ,fnameに再代入する
* retryでbeginの最初に
* 今度はopenで成功する
* 本来の処理
しかし,例えば再代入した名前のファイルも存在しなければ,この
例では無限ループに陥ってしまう.retryを使う時には,例外処理
に気を使った方が良い.
rubyのライブラリはエラーが起きた時に例外を発生させるようになっ
ているが,もちろん自分で例外を発生させることができる.例外を
発生させるには`fail'を使う.failには例外の状況を説明する文字
列を引数に与える.この文字列は説明する必要がない時には省略で
きる.この文字列は後から変数`$!'で参照できる.
ruby> fail "test error"
ERR: test error
ruby> begin
ruby| fail "test2"
ruby| rescue
ruby| print $!, "\n"
ruby| end
test2
nil