Prev - DUP - Next - TOC

Exception Processings


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:

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

Prev - DUP - Next - TOC