develooper 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


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About