Glenn Linderman wrote (in RFC 119 v2):
>
> RFC 119 wants to make available to the catch block exactly the
> same list of parameters supplied to throw. This is prevented
> by RFC 88's stringification and concatenation of parameters.
Not quite true. You can't get exactly the same list, but you can
get exactly the same list plus some more ;-)
try {
throw Exception "Can't foo.", params => \@params;
}
catch {
print "Params: ", join(", ", @{$@->{params}}), "\n";
}
> RFC 119 makes those parameters available to the catch block
> via @_, whereas RFC 88 doesn't presently make the
> parameters available.
RFC 88 makes the *exception* available via $@, and the params can
be kept in the exception, as illustrated above.
> RFC 88 uses the finally keyword as a subclause introducer for
> the try statement. RFC 119 uses the except and always keywords
> as subclause introducers for any statement.
RFC 88 uses finally *and* catch (just like always and except).
> RFC 119's except clause is executed only if an exception occurs,
> which exits the scope containing the statement in which it is
> defined.
Same as 88's catch clause.
> RFC 88's finally clause is executed if an exception occurs, or if
> flow of control falls out of the bottom of the try statement.
Same as 119's always clause, I believe.
> It is not clear whether the finally clause is executed if the
> try statement is exited via a goto or return, but the statement
> is made that once a try statement is entered, it is guaranteed
> that the finally clause is entered, but none of the
> discussion mentions exiting via goto or return.
Quote from RFC 88 + ISSUES + Mixed Flow Control:
Some of the reference texts, when discussing exception handling,
refer to the matter that it may be difficult to implement a
C<go to> across an unwinding semantics block, as in:
try { open F, $f } catch { next; }
This matter will have to be referred to the internals experts.
It's ok if this functionality is not possible, it can always be
simulated with lexical state variables instead.
> RFC 119's always clause is executed if an exception occurs, or if
> flow of control exits the scope in any other manner.
Same as 88's finally clause.
> If RFC 88's finally clause is executed when the try statement is
> exited via goto or return, then RFC 119 would be happy to rename
> its "always" clause to "finally", and the techniques would be more
> uniformly named.
RFC 88 proposes that finally is entered even after return in try.
RFC 88 acknowledges that this may not be possible, as quoted above.
RFC 88 and RFC 119 will either both be able to do it, or neither.
This would be obvious if RFC 119 used a try keyword, instead of
pretending to a "normal" local-flow-control block.
> RFC 88 has nothing that directly corresponds to RFC 119's
> except clause, although that logic could be included at the end
> of each catch clause.
No, you've completely mis-read RFC 88 here. Its "catch" clause
directly corresponds to 119's except clause, although I believe
catch is a bit more general purpose as proposed.
> For example, in the section "C++ like example", the 2nd
> example looks remarkably like RFC 88 syntax, but the 3rd example
> demonstrates a more concise representation not available in RFC
> 88.
Yes. The third example in 119:
my $handle1 = open ( ... ) always close ( $handle1 );
my $handle2 = open ( ... ) always close ( $handle2 );
my $handle3 = open ( ... ) always close ( $handle3 );
...
catch error_type_1 {
# report error type 1, handle it
}
catch error_type_2 {
# report error type 2, handle it
}
would look like this in 88:
try {
my $handle1 = open ( ... );
my $handle2 = open ( ... );
my $handle3 = open ( ... );
...
}
catch error_type_1 {
# report error type 1, handle it
}
catch error_type_2 {
# report error type 2, handle it
}
finally {
$handle1 and close ( $handle1 );
$handle2 and close ( $handle2 );
$handle3 and close ( $handle3 );
}
I completely agree with what 119's "always" does, and how nice and
concise the syntax is. I just think that should be a separate RFC,
that "always" should be invoked whenever the lexical variable it is
associated with goes out of scope (whether or not by unwind), and
that really, exception handling doesn't enter into it. It's just
a lexical destructor block.
> I believe that any needed exception handling logic can be
> expressed at least as concisely and clearly using RFC 119 than
> using RFC 88.
In order to convince me of this, you'll have to present a clear
set of examples of how RFC 119 handles the kinds of things shown
in the EXAMPLES section of RFC 88 (and, without all that C stuff).
> I'd like to see two modes of operation by the exception class:
> "normal" and "debug", where normal omitted many of the
> implicit features (preserving the call stack, debug info, object
> info, etc.), but could be turned on easily across all loaded
> modules via some command line switch.
RFC 88 acknowledges that the stack tracebacks may not always be
wanted, so only the "debug" attribute is really affected. To quote:
snapshot
Used internally to generate the "trace" instance variable.
Designed to be overridden in derived classes for performance or
extension purposes. See the description of the trace instance
variable, above.
It might be a good idea if the default snapshot method took a
dynamically scoped state variable into account, and maybe we could
just add it to a top-level try using the following syntax (already
proposed for other things in RFC 88):
try debug => 0, {
# no snapshots anywhere "under" here in call stack.
}
It probably would be a good idea if you clean up some of these
misconceptions in your next release of 119, just so people don't
get the wrong idea about 88 ;-) Thanks.
Yours, &c, Tony Olekshy