The execution and the exception always go together. Opening a file, the file may not exist; Writing a file, the disk may be full. A program is considerd to be of bad quality if it discounts these exceptions.
It is tiresome that we cannot know the occurrence without checking ``Was the process okay?'' each time. Some problems will certainly be caused if the continuation runs with the appropiate processes omitted for an exception. When an exception occurs the process should not go without coping with it.
In ruby, an exception occurs in such exceptional situations. If nothing copes with them, the exception stops the program. So we don't have to worry about running without exception processing.
ruby> file = open("/unexistant_file") ERR: No such file or directory - /unexistant_file
In C, the programmer must check for each critical situation, such as whether a file was opened or not. On the other hand, in ruby, we may assume `Since no exception occured the process succeeded'. The above ruby code must be written as follows in C:
FILE *file = fopen("/unexistant_file", "r"); if (file == NULL) { /* error recovery */ }
This shows that the ruby version is simpler because error processing is unnecessary.
As explained above, the program stops if an exception occurs.
But it is usually not good: In the most cases, you want to
continue the execution after some processings to cope with
the cause of the exception.
For such treatments, you should capture the exception by using
`begin
'. The following demonstrates this:
ruby> begin ruby| file = open("/unexistant_file") ruby| rescue ruby| file = STDIN ruby| end #<IO:0x93490> ruby> print file, "==", STDIN, "\n" #<IO:0x93490> == #<IO:0x93490> nil
You can see that `STDIN
' is substituted to `file
'
because `open
' failed.
`begin
' moves control to error
proccessing which follows `rescue
'.
`Retry' is available for `begin
' by `retry
'.
In a rescue
, `retry
' moves the control
to the beginning of the `
begin
'. See an application
below.
ruby> fname = "unexistant_file" ruby> begin ruby| file = open(fname) ruby| # something to use file ruby| rescue ruby| fname = "existant_file" ruby| retry ruby| end #<File:0x68890>
It failed opening a file and substituted another file name to
fname
, then retried.
The following is the flow of the process:
open
rescue
. fname
was re-substituted
retry
went to the beginning of the begin
Notice that if the file of re-substituted name does not exist
this example code retries infinitely.
Be careful if you use `retry
' for an exception process.
Every ruby library raises an exception if any error occurs,
and you can raise exceptions.
To raise an exception use `raise
'.
raise
takes one string argument as a message
which explains the error.
This argument can be omitted (but should not be omitted),
and this error message can be accessed by `$!
' later.
ruby> raise "test error" ERR: test error ruby> begin ruby| raise "test2" ruby| rescue ruby| print $!, "\n" ruby| end test2 nil