At 06:10 AM 8/17/00 -0600, Tony Olekshy wrote:
> catch "Error::DB" { ... }
>
> catch [ "Error::DB", "Error:IO" ] { ... }
>
> trap { $@->{message} =~ /divide by 0/ } catch { ... }
I don't think you need another keyword here. Just support an expression
argument to catch and you can do
catch $@->{message} =~ /divide by 0/ { ... }
If it needs to be more complicated, use 'do'; that should still make it
parseable. At the very worst it may need a comma the way map uses it,
which we can write as =>. But I don't think that'll be needed.
Note: I used to favor $_[0] for the exception, but I'm being won over to
$@. As long as it doesn't cause problems with external interfaces. Might
mention the $_[0] idea in a footnote.
> catch { ... }
>
> finally { ... }
Still want this to be "continue"; let's mention both.
>Any exceptions that are raised within an enclosing try, catch, trap,
>or finally block (anywhere up the subroutine call stack) are trapped
>and processed according to the semantics described in this RFC.
Maybe it's just me, but I think of 'up' the stack as being my callers, and
'down' being my callees.
>The new built-in Exception base class is designed to be used by Perl
>for raising exceptions for failed operators or functions, but this
>RFC can be used with the new base class whether or not that happens.
>
>=head1 DESCRIPTION
>
>exception 'Error::DB::Foo';
>
> Makes Error::DB::Foo into a class that behaves like a built-in
> Exception.
>
> If the given name matches /::/, something like this happens:
>
> @Error::DB::Foo::ISA = 'Error::DB';
>
> If the given name does not match /::/ (say it's just 'DB'), this
> happens instead:
>
> @DB::ISA = 'Exception';
I think you want to s/Error/Exception/ above. Then the rule is
simpler. Require all exceptions to be subclasses of 'Exception' for clarity.
>throw Error::DB => "a message", tag => "ABC.1234", ... ;
Suggest dropping the =>. Then throw can be implemented as an object method
and this is just the indirect object syntax. Do you really want to leave
out the "message =>" there? IMHO it looks confusing to tie the class to
the message and leave the message attribute name out. So I suggest
throw Error::DB (message => "a message", tag => "ABC.1234");
except that my vote is for "code" instead of "tag".
> Syntactic sugar for:
>
> die Error::DB->new(
>
> message => "a message", tag => "ABC.1234", ...);
>
> A throw with no arguments is syntactic sugar for re-raising
> the current exception. If there is no current exception,
> an anonymous Exception is manufactured first.
Um, I don't like that. What's an anonymous Exception? What would its
attributes be?
I think it's easier to require them to "throw $@" if they want to rethrow,
so you're not forced into this anonymous exception thing.
>catch { ... }
>
> Traps all exceptions, according to the unwind semantics
> described below.
>
> It is a syntax error for a catch all clause like this to be
> immediately followed by a trap clause or another catch clause.
>
> Otherwise, it is semantic sugar for trap { 1 } catch { ... }.
AFAIK, only syntax is sweetened. Semantics are inherently low-cal.
>catch "Error::DB" { ... }
I want to be able to drop the quotes. With 'catch' being a full-blown
keyword, this is possible.
>trap { ... } catch { ... }
>
> Traps exceptions for which the trap block returns true.
>
> It is a syntax error if the catch clause following a trap
> clause has a scalar before its block.
You won't have that loophole to close with the catch EXPR option.
>die
>
> If argument isa "Exception", raise it as the new exception and
> die in the fashion that Perl 5 does.
>
> If argument isa "UNIVERSAL", wrap it in a new Exception (using
> the "object" instance variable), and raise that instead.
Hmm... what is the benefit of being able to throw objects that aren't
exceptions?
> When an exception $e is raised, the following is automatically
> done:
>
> $e->{link} = $@; $@ = $e;
Only if $@ was defined, I presume.
> 1. Whenever an exception is raised Perl looks for an enclosing
> try/catch/finally block.
>
> If such a block is found Perl traps the exception and proceeds
> as per rule 2, otherwise program shutdown is initiated.
I wonder if we should anticipate the possibility of $SIG{__DIE__}
surviving... and saying that at this point it could get its horny little
hands on the exception.
>=head2 Built-In Exception Base Class
>
>In addition to the built-in Exception class described below, a
>built-in Error class is defined. The Error class inherits from
>Exception. Internal Perl assertion failures are instances of
>exception classes that inherit from the Error class. This
>results in code like C< catch "Error::IO::File" { } >. It
>also allows simple anonymous error exceptions to be raised with
>a form like this:
>
> throw Error => "message", severity => "Fatal";
I don't see what you mean by 'anonymous' here. I also think there should
be exactly one exception class hierarchy.
>trace
>
> A listref containing a snapshot of the call-stack as at the time
> the exception is first raised. The array contains hashes (one
> per call stack level), each containing one key value pair for
> each snapshot value at that level. Here are some examples:
>
> $e->{trace}->[0]->{file}
> $e->{trace}->[0]->{line}
> $e->{trace}->[0]->{sub}
>
> This snapshot is set up by the "snapshot" method, so that
> derived classes that don't want this overhead can override
> the method.
I know I was pushing for this, but Ive seen the light that in fact caller()
should be doing this for us. Can you see any reason that won't do?
>overload '""' => sub {
>
> my $t = exists $_[0]->{tag} ? $_[0]->{tag} . ": " : "";
>
> exists $_[0]->{severity} and $t .= "($_[0]->{severity}) ";
>
> $t .= $_[0]->{message} =~ /\S/
> ? $_[0]->{message} : "anonymous exception.";
> }
I think we should just be defining semantics here, not supplying code.
>=head1 EXAMPLES
>
>The following three examples conver the most common uses of try,
>catch, and finally.
>
> open(*F, ">foo"); try { ... } finally { close F; }
Why isn't the open inside the try block? Don't you want to see if it
succeeded?
See my earlier comments about all linked blocks sharing the same lexical
scope, btw.
>Keyword Names
>
> RFC 88 only introduces the try, throw, trap, catch, finally,
> and exception keywords, which are all traditionally related
> to exception handling. Also, "try" was chosen because of it
> neutral connotation (unlike "fail" for example), because
> exceptions do not necessarily encapsulate a negative.
I think throw and exception only need to be functions.
> because the author is of the opinion that overloading else and
> continue with unwind semantics not traditionally associated with
> else and continue can be confusing, especially when intermixed
> with local flow-control forms of else and continue, or when
> an "else throw" is forgotten on a switch that needs to re-throw.
>
> The "try" is not necessarily for Perl's sake. It's for the
> programmer's sake. It says, watch out, some sort of non-local
> flow control is going on here. It signals intent to deal with
> action at a distance (unwinding semantics).
Well said.
> How to arrange the exception class hierarchy for the Perl core?
This is the province of RFC 80. I can just remove the stuff that's already
been subsumed in this draft.
--
Peter Scott
Pacific Systems Design Technologies