

What's a condition system and why do you want one? - uros643
http://axisofeval.blogspot.com/2011/04/whats-condition-system-and-why-do-you.html

======
sedachv
One thing that hasn't been pointed out is how the Common Lisp condition system
provides a sane alternative to the Unix signal(7) brain-damage. To quote the
Hyperspec:

    
    
      If the condition is not handled, signal returns nil.
    

[http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec...](http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/fun_signal.html)

~~~
kragen
I think they really serve different purposes. signal(7) is a software
interrupt mechanism. Its purpose is to allow your program to respond to
external events without having to poll for them. (In particular, it provides a
way for your program to exit gracefully when it's stuck in an infinite loop
and the user kills it, and it provides a way for your program to handle page
faults in userland — too bad the parameters needed to handle page faults
aren't standardized across Unices.)

Like other interrupt mechanisms, it also gets used for error exits in
languages that don't have them inherently, but it's a pretty bad way to do
that.

~~~
sedachv
If you take a look at Kent Pitman's paper, linked from the post,
([http://www.nhplace.com/kent/Papers/Condition-
Handling-2001.h...](http://www.nhplace.com/kent/Papers/Condition-
Handling-2001.html)), particularly the section 'Unifying "Signals" and
"Exceptions"', he points out that signal(7) is actually doing two orthogonal
things - process interrupt, and signal raising.

He also points out how the signal(7) and Lisp conditions came out of Multics.
If you consider it that way, it becomes clear that the Unix decision to
overload signal(7) with two different functions is why it is such a poor
interface and major source of pain.

------
5l
For Ruby, check out <http://cond.rubyforge.org/>

------
Groxx
Interesting... I was just coming to the conclusion that such a thing would be
handy, as so many things use exceptions as a way of, essentially, returning
multiple values. It's rampant - add an item to a set where it already exists,
and it throws. Which costs a _lot_ compared to returning false due to the
stack-unwinding, but is more flexible. Typically though, the stack-unwinding
is entirely unnecessary, the class / message is more than enough to determine
the source of the problem. And such a thing would turn try/catch blocks into a
loosely-coupled implicit delegate system, which strikes me as fantastically
useful.

~~~
kragen
> Which costs a _lot_ compared to returning false due to the stack-unwinding

The relative costs are dependent on the language implementation. longjmp() in
C is only roughly as expensive as a normal function return, but of course
setjmp() costs an extra two or three function calls' worth. And in many
interpreters, exceptions are basically free.

(Except on MacOS, where setjmp() and longjmp() are an order of magnitude
slower because they involve system calls.)

I had a discussion with a mainframer a couple of years back about what kinds
of things people did in assembly that aren't reflected in C. One interesting
technique he mentioned was incrementing the return address in case of error
returns, so the function actually had two different possible points to return
to; the calling code would look something like this (x86 version):

    
    
            CALL SOMEROUTINE
            JMP 1f
            JMP ERROR
        1   ; continue with normal processing
    

In case of error, the routine bumped its return address by the size of a jump
instruction before returning to the JMP ERROR instruction.

Such a pattern would be awfully disconcerting if you weren't used to it, of
course.

Multiple return values were, of course, another thing he mentioned. Any
caller-saved register can double as an additional return value.

------
thurn
Would this be pretty easy to implement in a language with first class
functions (albeit with more boilerplate) just by keeping a list of functions
to be invoked before raising an exception?

~~~
rfk
You can get most of the way there using such an approach, but it'll never feel
quite "right" unless your language gives you lots of syntactic sugar to play
with.

You've also got to be careful about how your handler stack interacts with
threads and/or coroutines.

For an example that I think same up pretty well, but certainly not as elegant
as the system built into lisp, check out my "withrestart" python module:
<https://github.com/rfk/withrestart>

