Charlie Reitzel wrote:
> I was quietly reading this thread, but I must respectfully but
> strenuously disagree with the premise that exceptions are "simply
> another kind of flow control".  OK, semantically exceptions _are_
> another type of flow control.  Let's not jump down a rathole.  But,
> in any language, exception-safe code is much harder to write than
> most programmers realize.

I don't know how strenuous your disagreement is when we seem to agree about
exceptions as flow-control.

It sounds like you want to strenuously make a point about how this
programming concept is non-trivial.  I agree.  I'd similarly agree that
threads, objects and lots more are more complex than people might think.
Programming is hard and requires knowing both the machine and the problem

Of these, the machine space is the easier one. Everything (nigh-everything)
is just math & flow control.  And flow control is just test & goto.  What
makes programming hard are the attempts to model problem spaces and
formulate languages and concepts appropriate to those models.

When I said exceptions are just flow control, I meant it in the broad,
almost-trivial machine sense.  Any given language model can implement them
in a way that makes it inappropriate to use them that way; but that's the
basic idea as modeled by setjmp/longjmp.

> If every method is re-entrant, there is nothing to worry about
> because stack unwinding deals effectively with method-local state.
> But as soon as methods start affecting the longer term running state
> of a system, exceptions can easily leave that system in an
> inconsistent, possibly broken state.

This is why many languages provide TRY...FINALLY, eh?  And others use
lexically guaranteed destructors to the same end.  That Perl provides
neither is one of the flaws in its exception handling.

> True, bad code can do all that without the "benefit" of exceptions.
> But, even otherwise solid code can go horribly wrong because
> exceptions are thrown in a 3rd party library.  Non-throwing code is
> much, much less likely to have that impact.

One can make the same form of argument against using threads, objects,
etc... Things can go horribly wrong in many ways for many reasons.  

One of the problems with the Perl "You can have exceptions if you want them"
approach is similar to that of C's "Threads arrived later" -- lots of code
assumes no one will be using exceptions/threads, so is not "safe" in the
presence of those things being added.  An advantage of the Java "We have
threads & exceptions -- they may be implemented badly, but they're always
there" approach is that all programmers are aware that those things are
there, and they (if at all competent) make some plan to deal with it.
(Typically badly, but safely.)

> This is the reason why coding standards for systems with very high
> uptime requirements often disallow throwing exceptions.  This can
> extend to disallowing use of libraries that throw (or taking pains
> to configure libs so that they do not).

This is one of those things which is pseudo-true.  Obviously, neither using
nor avoiding flow control is a guarantee of uptime. (Though perhaps not
using flow control is a guarantee of minimal uptime.)

What this policy is really saying (as I'd read it) is that, in an effort to
avoid program defects, the program behavior should be kept as simple and
obvious as possible.  Which is fine.  Until/unless you reach a point where
it conflicts with another requirement, such as hard, real-time performance.

Say you have code in a tight loop which has to call N functions, and if any
of them returns X (which isn't considered an error), it has to return.
Without exceptions, that means performing N tests.  With exceptions, it
requires no tests at all -- the functions themselves can simply throw 'X'
when it happens.  And before (or just after) you think it -- yes, that's a
very vague example fraught with potential alternatives.  But, it expresses a
good use-case for fast, goto-like, not-just-for-errors exceptions.  (Just to
mention, an alternative, similarly efficient approach is to use
continuations of some type and allow each function to decide between passing
control to "keep-trying" or to "X-happened" alternatives.)

> Put another way, the "rare" nature of Exceptions (go figure) is
> implied in the sub-optimal treatment given by compiler writers to
> exception code paths.  You sure as heck don't want to optimize
> Exceptions at the expense of the regular, non-Exception code paths!

Slow exception implementations are suitable only for rare code-paths.  But
that does not mean that setjmp/longjmp are slow and can only be used rarely.
You're somewhat inverting the cart and horse.

Also, there is little or no tradeoff (this can depend on the CPU) for having
exceptions present in a language -- but once you allow them at all; you have
paid the penalty.  (The penalty is related to "return" and "try...finally"
-- essentially, every "return" must become equivalent to an exception, so it
will hit the "finally" handlers properly.  Or, similarly, so it will call

Once present, the speed of exceptions is only constrained by how much
"stuff" one adds on top of the longjmp-or-equivalent implementation.  For
example, if every exception starts by tracing the stack & gathering debug
information that can later be used in an error message.. that's going to be
a little slow.  A language can offer the programmer a choice of throwing
"fast" or "slow" exceptions, depending on what they're used for.

Boston-pm mailing list

Reply via email to