Front page | perl.perl5.porters |
Postings from April 2008
RFC: Fatal/autodie exception handling naming and structures
Thread Next
From:
Paul Fenwick
Date:
April 4, 2008 22:31
Subject:
RFC: Fatal/autodie exception handling naming and structures
Message ID:
47F70E8E.9040603@perltraining.com.au
G'day p5p,
I'm back to working on Fatal/autodie after a number of weeks of travelling
and teaching, and I'm musing a little more on the details of exceptions for
Fatal/autodie. This mail is mainly idea bouncing, to see if anyone feels my
suggestions are particularly good or particularly bad.
With the code I've got so far, we can write something like:
use autodie qw(:io);
to turn on automatic throwing of exceptions for all I/O operations with
lexical scope. However these exceptions are just plain strings, which sucks
when it comes to exception handling. There seemed to be broad support for
making the exceptions proper objects, so I'm doing exactly this.
Since autodie is 5.10 only (we need %^H for lexical goodness), I'm drawn
heavily to using given/when for exception handling. For the following
example to work, it's assumed that exceptions from autodie will overload ~~
(smart-match) to provide the desired behaviour:
given ($@) {
when (undef) { say "No error"; }
when ('open') { say "Error thrown from open built-in"; }
when (':file') { say "Error from file-related built-in"; }
when (':socket') { say "Error from socket-related built-in"; }
when (':io') { say "I/O error from other other built-in"; }
default { say "Any other sort of error." }
}
Note that a plain string is counted as the name of a function, and we test
to see if that function was the source of the error. A string starting with
a colon indicates a group, and we test to see if the error-causing function
is a member of that group. A sample exception hierarchy may look like this:
:CORE
:io
:file
open, close, sysopen, syswrite, etc
:socket
accept, bind, connect, socket, etc
:directory
opendir, chdir
The hierarchy will match the options that can be used when invoking autodie,
so if one were to write:
use autodie qw(:socket :file)
then any exception thrown due to autodie should smart-match successfully
against either :socket or :file.
Errors from autodie will include methods to obtain the file and line number
where the error occurred, the arguments passed to the offending function,
and the ability to stringify to nice-looking error messages. API
suggestions are welcome here, although I'm inclined to borrow heavily from
Exception::Class::Base.
Things I'm not so sure about:
* The root of the exception hierarchy for built-ins being
accessible by ':CORE'. Is there a better label that can
be used?
* What should we use as a root label for errors from user-defined
subroutines, such as 'copy' in the following example:
use File::Copy qw(copy);
use autodie qw(copy);
I'd consider ':USER' as a reasonable counterpoint to ':CORE',
but I'm happy for other suggestions.
* What should be the ultimate root label for all autodie exceptions,
so that users can determine the difference between them and
all other errors? Since I want the errors from Fatal and autodie
to be the same, my first thought of ':AUTODIE' isn't fantastic.
We need an ultimate root so that a developer can write:
given ($@) {
when (':AUTODIE') { say "Error from Fatal/autodie"; }
default { say "All other errors."; }
}
Comments, feedback, ideas, suggestions, and criticism all very welcome.
Cheerio,
Paul
--
Paul Fenwick <pjf@perltraining.com.au> | http://perltraining.com.au/
Director of Training | Ph: +61 3 9354 6001
Perl Training Australia | Fax: +61 3 9354 2681
Thread Next
-
RFC: Fatal/autodie exception handling naming and structures
by Paul Fenwick