This and other RFCs are available on the web at
  http://dev.perl.org/rfc/

=head1 TITLE

Exception handling syntax

=head1 VERSION

      Maintainer: Peter Scott <[EMAIL PROTECTED]>
      Date: 8 Aug 2000
      Last-Modified: 12 Aug 2000
      Version: 2
      Mailing List: [EMAIL PROTECTED]
      Number: 63

=head1 ABSTRACT

This RFC proposes an exception handling syntax for Perl 6 adapted from
that used in Graham Barr's C<Error.pm> module.

=head1 DESCRIPTION

An exception handling mechanism is proposed with the following syntax:

     exception EXCEPTION

     try BLOCK catch [EXCEPTION [, ...] ] BLOCK ...
     try BLOCK catch [EXCEPTION [, ...] ] BLOCK continue BLOCK

     throw EXCEPTION [ (attributes) ]

Exceptions thrown in the C<try> block cause immediate termination of
processing of the C<try> block.  Perl then looks through the C<catch>
blocks in order for one which either names the class the exception
belongs to, or which names none, therefore catches all.  If it finds
one, it executes the code in that block.  It then executes any
C<continue> block.  At that point, if the exception had been caught,
processing continues with the next statement; if it was not caught,
it is propagated up to any enclosing C<try> block and the process
repeated.  The exception object is passed into each block in C<$_[0]>.

An uncaught exception with no enclosing C<try> block causes the program
to C<die> with the text in the C<message> attribute of the exception,
which is what the exception stringifies to.

A C<continue> block is a Java C<finally> block; it gets executed after
the C<try> block, after any C<catch> blocks, but before any uncaught
exception is re-thrown.  In this case we were inheriting syntax from
Perl rather than another language.

Note that C<try> is a keyword, not a function.  This is solely so that
a C<;> is not needed at the end of the last block, since so many people
are bound to think it shouldn't be there and forget.

There is debate over whether C<try> should be C<eval> so as not to use
another keyword.  Since it has different semantics (rethrows uncaught
exceptions), it should not be C<eval>; but if this happens, then surely
C<eval BLOCK> should be retired since it is so similar there would be
confusion over what to use for exception handling.  And no-one would
get the semicolons right :-)

A C<try> block without any C<catch> blocks would be pointless, since
uncaught exceptions (i.e., all of them) would be rethrown.

While C<try> and C<catch> are new keywords, C<throw> and C<exception>
don't need to be; they're just functions.

=head2 Exceptions

Exceptions are objects belonging to some C<Exception> class.  C<throw>ing
an exception creates the object; therefore, C<EXCEPTION> above is just a
class name.  C<Error.pm> lets you subclass C<Error> to create them;
C<Exception> appears to be a better name for a core functionality.

The C<exception> function is just syntactic sugar for creating a new
exception class, although it merely amounts to C<@EXCEPTION::ISA = 
'Exception'>.

RFC 80 proposes standard exception classes and methods for core
exceptions.

=head2 Examples

These examples assume some core exception classes, although the
mechanism can be implemented even if core exception classes aren't.
The nature of exceptions is that they are most useful on lengthy code;
code brief enough to be a readable example also makes a functionally
poor example.

     exception Exception::MyDB;
     sub foo {
         open_database();
         # database-munging code
         throw Exception::MyDB(message => 'permission denied');
         close_database();
         open_network_connection();
         # network munging code
         throw Exception::IO(message => 'timeout');  #  In Socket.pm, perhaps
         close_network_connection();
         }

     try {
         foo();
     } catch Exception::MyDB, Exception::DBI {
         close_database();
         # other stuff
     } catch Exception::IO {
         close_network_connection();
         # other stuff
     } catch {
         my $err = shift;
         warn "Some other kind of error in foo: $err\n";
         throw $err;      # Re-throw exception (just 'cuz we wanted to)
     }

=head1 IMPLEMENTATION

A C<throw> is just a C<die> passed an object that stringifies to the
message you will die with if nothing catches the exception; therefore
users can use code that throws exceptions without using the exception-handling
mechanism.  They should also be able to wrap a C<try> block around code
that doesn't know about exceptions but does call C<die>, and have that
caught as well; perl should turn the C<die> text into an exception object
with the same text, in the base C<Exception> class.

=head2 $SIG{__DIE__}

<$SIG{__DIE__}> needs to be triggered only as a I<last> resort
instead of firing immediately, since it messes with the mind of this and
every other decent exception handling mechanism.  Perhaps it should be axed
altogether.

=head1 NOTES

This RFC is very similar to RFC 88, which has slightly different syntax
and adds functionality for adding exceptions to a stack.  While this author
considers that to be going a bit too far (he's tried it before and found he
never made use of anything under the top level of the stack), he wouldn't
mind if RFC 88 got adopted instead.  This RFC is attempting to stake out a
more minimalist position.  Some people think it should be even more minimal
by using C<eval> instead of C<try>, and C<else> instead of multiple C<catch>
blocks.

=head1 REFERENCES

Error.pm (C<http://search.cpan.org/doc/GBARR/Error-0.13/Error.pm>)

RFC 80: Exception objects and classes for builtins

RFC 88: Structured Exception Handling Mechanism (Try)

Reply via email to