Re: RFC 63 (v2) Exception handling syntax
At 07:07 AM 8/12/00 -0600, Tony Olekshy wrote: >One problem I still see with RFC 63 is that there is no syntax for >doing a string match on the exception's stringification, as in the >RFC 88 syntax: > > except "division by 0" => catch { } > except qr/div.* by 0/ => catch { } That's a feature :-) Selecting exceptions by regex matching on the text attribute is a bad idea, IMHO. What if the message changes in the next release? What if we one day figure out i18n and the message is in French? Note the commonality of RFCs 80 and 85, suggesting that error messages be identified by fixed, unambiguous identifiers. However, RFC 63 could still do it with catch { my $err = shift; switch ($err->message) { case /division by 0/ : { } > > A C block without any C blocks would be pointless, > > since uncaught exceptions (i.e., all of them) would be rethrown. > >Whoa. What about making sure that if a file is opened then it >is closed, even if the processing between open and close throws, >as in: > > open(*F, ">foo") or throw ...; > > try { ... } > > finally { close F or throw ...; } Ah, thanks. Hadn't thought about using a finally block there. >It's a pleasure to work with you on these matters. Ditto. > It appears >to me that Peter's approach in RFCs 63 and 80 represents the >perspective that the exception is the key and handling is just >what you do with it, whereas my approach in RFCs 88 and 96 is >that handling exceptions is the key, and the exceptions are just >what you happen to be handling. I think it's important to remember that we're just coming up with ideas here for the people who make the design decisions on P6 to chew over, not coming to final decisions ourselves. So I view multiple overlapping RFCs as a good thing; they indicate that there is a common need, that there are differing sub-needs, and leave open the possibility for a greater genius to find a solution that makes everyone happy. -- Peter Scott Pacific Systems Design Technologies
Re: RFC 80 (v2) Exception objects and classes for builtins
At 07:07 AM 8/12/00 -0600, Tony Olekshy wrote: >Peter Scott wrote, in RFC 80 (v2): > > > > =item id > > > > Unique numeric identifier, assigned by perl developers. > >I'm loath to bother everyone with this I've redirected to perl6-language-flow. They're supposed to enjoy being bothered with it :-) >, but to me the id of an >object should be unique to each *instance* of the class. If we had > > my $e = Exception->New(id => "ABC.1234"); > my $f = Exception->New(id => "ABC.1234"); > >then $e and $f would have the same id, but be different objects. Yes, the implicit registry bothers me too - not for the core: I figure the perl developers can manage a little enumeration class - but for external stuff. CPAN could conceivably work since they already have a registry for the naming hierarchy, but what about when you want to write an in-house thingy and make sure the ids don't collide with anything else you get? Number ranges for user space (e.g., negative numbers) are all well and good, but eventually you'll have two or more separate things both living in user space but constructed independently. I was attempting to carry RFC 85 to its logical extension, but perhaps I stretched it too far. I think it's not as bad as you imply though. We could disambiguate id tags by checking the exception class name, since it's reasonable to assume that anything throwing an exception in a particular class will coordinate ids with everything else doing the same. > > Line number exception was thrown at. > > File exception was thrown in. > >Should this be line thrown at or line constructed at? Does anyone >care? There is an issue of how far up the call stack you should go. If I write main.pl: 1 try { 2 foo($obj); 3 }; 4 sub foo { 5 $_[0]->bar(); 6 } Foo.pm: 100 sub bar { 101 pling(shift); 102 } 103 sub pling { 104 throw Exception::Baz unless blech(shift); should the (file, line) be: (main.pl, 2), or (Foo.pm, 101) or (Foo.pm, 104)? Clearly if you wrote Foo.pm you'd like the last one, and if you didn't, you'd like the first one. Well, probably you'd want all of them. Hmm - what if we made line() and file() return arrays? Then we'd also like uncaught exceptions that result in program death to at least have the option of a confess() backtrace, and the data would be in the object. > > Stringifying the object itself will yield the C attribute. > >Or perhaps a formatted combination of a subset of the attributes, >as in RFC 96? Or the confess() I just suggested above, yes. -- Peter Scott Pacific Systems Design Technologies
Re: RFC 63 (v2) Exception handling syntax
Peter Scott wrote, in RFC 63 (v2): > > 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. The author of RFC 88 (that's me) agrees with you that it is going a bit too far. In fact, we mainly use the exception stack to generate those fancy tracebacks into server logs, not to catch them per se. I'm planning to revise RFC 88 to pull out the default stack handling, but to provide hooks to allow such a stack to be maintained via use of a module. Then, it's available for the fancy stuff, and the except => sub { } => catch { } syntax and/or the catch { switch } syntax can be used to deal with those rare special cases where one would want to examine the stack (if it's enhooked). One problem I still see with RFC 63 is that there is no syntax for doing a string match on the exception's stringification, as in the RFC 88 syntax: except "division by 0" => catch { } except qr/div.* by 0/ => catch { } That's why RFC 88 provides both this form and the "except isa" form. (Note that I'm planning to revise RFC 88 to require the form "except match => 'foo'" or "except match => qr/foo/" to remove the difficult rule about the reserved lower-case stuff, and to add forms like "except tag => 'ABC.1234'" and "except severity => /^(Fail|Fatal)$/', depending on how RFC 96, A Base Class for Exception Objects, pans out.) I'm also planning to revise RFC 88 to take a listref of strings or REs wherever it currently takes a single string or RE, as in the "except match" and "except isa" forms. Thanks to everyone who participated in the discussion on this matter. > A C block is a Java C block; it gets executed > after the C block, after any C blocks, but before any > uncaught exception is re-thrown. In this case we were inheriting > syntax from Perl rather than another language. > Some people think it should be even more minimal by using C > instead of C, and C instead of multiple C > blocks. As I mentioned elsewhere, it seems to me that continue connotes some sort of looping thing, not "whether or not unwinding". I'd much rather take the hit of a new but traditional exception handling keyword like "finally", than the hit of conceptually overloading continue in this case. Minimalism only goes so far, in the sense that even Bauhaus and wabi sabi tend to have doors that are not the same as windows. And I'm no lexicographer, but I think finally pre-dates Java. There's another thing too. If we use finally instead of continue, then we can continue to maintain a Perl 5 implementation. This means that (1) we can continue to experiment with the implementation and build regression tests before Perl 6 is born, and (2) Perl 5 programs and modules can begin to migrate to the new exception object and exception handling mechanism while still running in Perl 5. The value of these benefits may be greater than epsilon. > A C block without any C blocks would be pointless, > since uncaught exceptions (i.e., all of them) would be rethrown. Whoa. What about making sure that if a file is opened then it is closed, even if the processing between open and close throws, as in: open(*F, ">foo") or throw ...; try { ... } finally { close F or throw ...; } or making sure an object's clean-up routine is called, in cases where the default GC doesn't do the job for you, as in: my $o; try { f ( $o = SomeClass->New ); } finally { $o and $o->Done; } > The C function is just syntactic sugar for creating > a new exception class, it merely amounts to @EXCEPTION::ISA = > 'Exception'. That reminds me, I need to revise RFC 96 to add a throw constructor and to allow some sort of construct like: use Exception Class => "Database::Write"; > RFC 80 proposes standard exception classes and methods for > core exceptions. I also submitted RFC 96, which tries to address the stuff that is needed for extending beyond builtins while maintaining a standard Perl OO implementation and seperating the exception handling stuff from the exception class. Rereading RFC 80, I realize that they are closer than I thought, each emphasising different aspects of the problem. No doubt we can eventually merge these, as may become the case with 63 and 88 as well. It's a pleasure to work with you on these matters. It appears to me that Peter's approach in RFCs 63 and 80 represents the perspective that the exception is the key and handling is just what you do with it, whereas my approach in RFCs 88 and 96 is that handling exceptions is the key, and the exceptions are just what you happen to be handling. We should be able to do a pretty good job of putting these two p
RFC 63 (v2) Exception handling syntax
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 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 block cause immediate termination of processing of the C block. Perl then looks through the C 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 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 block and the process repeated. The exception object is passed into each block in C<$_[0]>. An uncaught exception with no enclosing C block causes the program to C with the text in the C attribute of the exception, which is what the exception stringifies to. A C block is a Java C block; it gets executed after the C block, after any C 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 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 should be C so as not to use another keyword. Since it has different semantics (rethrows uncaught exceptions), it should not be C; but if this happens, then surely C 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 block without any C blocks would be pointless, since uncaught exceptions (i.e., all of them) would be rethrown. While C and C are new keywords, C and C don't need to be; they're just functions. =head2 Exceptions Exceptions are objects belonging to some C class. Cing an exception creates the object; therefore, C above is just a class name. C lets you subclass C to create them; C appears to be a better name for a core functionality. The C 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 is just a C 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 block around code that doesn't know about exceptions but does call C, and have that caught as well; perl should turn the C text into an exception object with the same text, in the base C class. =head2 $SIG{__DIE__} <$SIG{__DIE__}> needs to be triggered only as a I 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 min
RFC 96 (v1) A Base Class for Exception Objects
This and other RFCs are available on the web at http://dev.perl.org/rfc/ =head1 TITLE A Base Class for Exception Objects =head1 VERSION Maintainer: Tony Olekshy <[EMAIL PROTECTED]> Date: 12 Aug 2000 Version: 1 Mailing List: [EMAIL PROTECTED] Number: 96 =head1 ABSTRACT A number of topics in the Perl 6 RFC discussions have touched on the concept of a sanctioned or canonical base class for exception objects. This RFC considers a basic proposal for a base class for exception objects that can be used with core Perl, traditional eval, die, and $@ functionality, and with exception handling mechanisms like RFC 63 and RFC 88. =head1 DESCRIPTION One of the attributes of an exception object is its class name. This can be changed via inheritance, and a hierarchy of isa relationships can be arranged. Exception handing mechanisms can arrange to have catch behaviour depend on these relationships. =head2 Instance Variables The following exception object instance variables are supported by this base class. tag This is a string which module developers can use to assign a unique "identifier" to each exception object constructor invocation in the module. What should the default be if not otherwise specified? severity This is some sort of "priority" (such as info v/s fatal) on which handing can be based. The details need to be worked out. What should the default be if not otherwise specified? message This is a description of the exception in language intended for the "end user". This is the only required ivar, so as such the constructor treats it specially. debug This is a place for additional description that is not intended for the end user (because it is "too technical" or "sensitive"). file The file from which the constructor was called. line The line from which the constructor was called. object If the exception is related to an object, it can be specified here. Should this be a weak reference? sysmsg This a place for the internal exceptions raised by Perl to record system information, along the lines of $!. =head2 Methods Only constructor and accessors so far. =head1 IMPLEMENTATION This is a bit minimalist, but it's a start. package Exception; use overload '""' => sub { my $t = exists $_[0]->{tag} ? $_[0]->{tag} . ": " : ""; exists $_[0]->{severity} and $t .= "($_[0]->{severity}) "; $t .= $_[0]->{message} =~ /\S/ ? $_[0]->{message} : "anonymous exception."; $t } sub new { my ($C, $msg, %A) = @_; exists $A{file} or $A{file} = caller ... exists $A{line} or $A{line} = caller ... exists $A{sysmsg} or $A{sysmsg} = magic ... bless {message => $msg, %A}, ref $C || $C; } sub tag { @_ > 1 and $_[0]->{tag} = $_[1]; $_[0]->{tag} } sub severity { @_ > 1 and $_[0]->{severity} = $_[1]; $_[0]->{severity} } sub message { @_ > 1 and $_[0]->{message} = $_[1]; $_[0]->{message} } sub debug{ @_ > 1 and $_[0]->{debug}= $_[1]; $_[0]->{debug}} sub file { @_ > 1 and $_[0]->{file} = $_[1]; $_[0]->{file} } sub line { @_ > 1 and $_[0]->{line} = $_[1]; $_[0]->{line} } sub object { @_ > 1 and $_[0]->{object} = $_[1]; $_[0]->{object} } sub sysmsg { @_ > 1 and $_[0]->{sysmsg} = $_[1]; $_[0]->{sysmsg} } =head1 IMPACT Once a standard set of attributes is decided on, RFC 88 can be revised to provide exception tests like: except tag => "ABC.1234" => catch { ... } except severity => "Fail" => catch { ... } =head1 ISSUES How to extend ivars and control namespace? How to extend methods and control namespace? Default values for tag and severity? How to categorize severity? How to arrange the exception class hierarchy for the Perl core? How to tag exceptions in the Perl core? What assertions should be placed on the instance variables? What should stringification return? =head1 REFERENCES RFC 70: Allow exception-based error-reporting. RFC 80: Exception objects and classes for builtins. RFC 63: Exception handling syntax proposal (Error.pm) RFC 88: Structured Exception Handling Mechanism (Try.pm)