Glenn Linderman wrote:
> 
> Tony Olekshy wrote:
> >
> > You are oversimplifying by mixing the notions of exceptions
> > and errors, whether you are aware of their difference or not.
> 
> I am aware of the difference between errors and exceptions;
> however, I firmly believe that exception handling is the best
> way presently known to mankind to handle non-fatal software
> errors, and often do lapse into speaking about them identically.

I completely agree.  I withdraw my oversimplifying comment.

I just don't think that with with respect to the infrastructure
mechanism per se, "fatality" should have anything to do with it.
In the end, that's a judgement call; that's what we get paid the
big bux for ;-)

> I have personally never found a need to signal success with an
> exception, and have never found a way that exception handling
> assists in the transmission of warning data to higher levels of
> software.  No doubt this contributes to my lapse.

We have a model-view-controller implementation of an engine that
implements engineering standards worksheets (such as for the ASME
Boiler & Pressure Vessel Safety Code).  We use exceptions to tell
view objects about the status of controller requests, and really
error and fatal don't enter into it.  But, as we've already
discussed, the cost of a raise-time snapshot might be prohibitive
for such non-error exceptions, since hundreds are raised during
a single worksheet evaluation.  Thus, as we say, the difference
between exceptions and errors.

But hey, in practice, exceptions are used for errors.  That's why
RFC 88 doesn't completely leave the definition of Exception up to
RFC 80.  RFC 88 has to try to make sure that no matter what RFC 80
does, RFC 88 still works for non-error exceptions.

> Some other error handling techniques provide a "sideband" channel
> that can be used for error data, warning data, and informational
> data.

If $@ isa Exception, you can use overriding and extension to create
all the sideband channels you want, as long as we come come up with
a namespace management standard, or Perl 6 objects get smarter.
Either way, that's one of the good reasons for actually making $@
an instance of Exception, rather some non-blessed structured data
type.

> Transmitting such information is extremely useful in a client/
> server (or multi-tier) environment, but generally the only way to
> handle it is to log the warning and informational data into a
> server side log facility, and hope an administrator peruses and
> processes it.

In our client/server transactions, if a top-level API catch all in
the server triggers, a text-formatted version of @@ information is
sent to the client in some sort of Error field (think XML).  Yes,
this means that when we turn on debug, we can actually get multiple
@@ and raise-time Perl call-stack tracebacks from multiple machines
in the developers browser.  And remember, all our throws have unique
tags, so we're just a grep away ;-)

> Unfortunately, some of that information would be useful to the
> user if obtainable in an interactive fashion, but that is hard to
> do.

Not with RFC 88.  Our Perl-5-based Try.pm version already does it.
See reference [TRY-2000] in RFC 88.

> > You are overcomplicating because you have two mechanisms, one
> > for fatal and one for non-fatal, when in fact they are the same.
> 
> You're trying to reduce their differences to a single bit (fatal
> bit on or off!), and maybe you can.  If doing so doesn't make
> using or understanding the mechanism inordinately complex, I have
> no problem with merging them.  If the complexity gets too great,
> then I think it is better to keep them separable mechanisms, each
> with their own particular features and benefits.

Agreed.  That's why I'm glad you're pushing me on this matter of
an option to automatically make some "kind" of exceptions immune
from catching.  If we're going to make RFC 88 live up to the
addition of the word "Omnibus" to its title, it bloody well better
be able to satisfy your needs (as long as they are reasonable, for
some value of reasonable, of course).

> Per Dan's posting and my response to it, separate mechanisms would
> allow the non-fatal mechanism to avoid dealing with hardware
> faults, should hardware faults get exposed as just another fatal
> error.

I don't read it like you.  I think he was saying that there are some
kinds of hardware errors that you should not be able to "catch" with
"eval", such as segfault.  Unless I'm mistaken, this means the
exception handling mechanism doesn't enter into it, since these
puppys can't be handled "by definition".

> > Right, but that didn't predermine how they were handled, it was up
> > to the catcher to check the classification.
> 
> One could consider that either a bug or a feature.  Predetermining
> the technique by which it was handled could be a boon in some
> instances, and could add complexity (need to use both mechanisms)
> in other instances.

Yes, but that's of less importance if it's a boon to a fundamentally
flawed technique.  And remember, only one "mechanism" is involved
(syntax aside).

> > Nope.  die is still die.  throw is die too, in fact, RFC 88
> > literally defines throw in terms of die.  RFC 88 doesn't change
> > how die works.  It only changes what $@ is (while preserving
> > stringification for "traditional" use), nothing else.
> 
> You can say that, but now since you are trying to catch non-fatal
> exceptions by wrapping try blocks around most everything,
> perfectly good die statements that used to kill the program now
> suddenly have to be handled.  Before you wrap the try's around,
> they handled themselves by killing the program.

They still do, unless you explicitly catch them.  Be calm.  In
practice, we have one throw per printed page in our code, and one
try per ten printed pages (this from a sample of 300 pages of
production web-app Perl code).  You are *not* going to be "wrapping
try blocks around most everything".  It doesn't happen in practice.
And when it does, you use the scoped pragmas to revert to high-speed
low-level return based error signalling (see, I told you it wasn't
going away--we do that all the time, and if one of them gets an
arithmethic overflow exception on ++$i, hey, no problem, we've got
lines of catch defenses set up to deal with that).

> RFC 119 keeps them orthogonal.  The techniques are independent
> techniques, the set of errors handled doesn't overlap:
> intersection of errors handled is empty.  dot product = 0.
> 
> RFC 88 makes them the same, with two syntaxes to choose from.  dot
> product = 1.

Suddenly I see your reasoning.  If the sets are disjoint, the dot
product is zero.  Of course.  But, still, I don't think the sets are
disjoint.  The set of "fatal" exceptions is a subset of the set of
"all" exceptions (which includes "non-fatal" exceptions), no matter
how I slice it.

> > RFC 88 suffers from no traditional die/eval problem because
> > turning it on doesn't affect their behaviour at all.
> 
> I misspoke when I said "turning on RFC 88" affects the behavior of
> die/eval.  It doesn't.  They work just as before.  However,
> actually wrapping a bunch of code inside a try block affects how
> that code reacts to die, thus affecting the behavior of the
> program that previously used die to mean terminate the program.

Hang on, this can't be true. To quote from RFC 88:

    try { may_throw_1 }
    catch may_throw_2 => { may_throw_3 }
    finally { may_throw_4 }

is exactly the same as (assuming traditional Perl semantics):

    eval { may_throw_1 };
    my $exception = $@;
    if ($exception) {
        my $test = eval { may_throw_2 };
        $@ and $exception = $@;
        if ( ! $@ and $test ) {
            eval { may_throw_3 };
            $exception = $@;
            }
        }
    eval { may_throw_4 };
    ($exception ||= $@) and die $exception;

How can this affect how code reacts to die?  It reacts the same
as with eval, whether wrapped in a try or not.  Say I had:

        do_something();

now I wrap it in a try:

        try { do_something(); }

this is equivalent to:

        eval { do_something(); };
        my $exception = $@;
        $exception and die $exception;

Which is *exactly* the same as bare do_something(); as per Perl 5.

Yours, &c, Tony Olekshy

Reply via email to