Lisp conditions - more powerful than exceptions
Jun 26th, 2006 by Phil Dawes
I was surprised to find that lisp had a more powerful way of dealing with errors than exceptions (which I had previously assumed were state-of-the-art in program error handling).
Lisp conditions are similar to exceptions, except that the condition handler is able, if desired, to resume execution to the erroring function by invoking one of any named ‘restart points’ declared by that function.
To understand why this is important, the Seibel book illustrates the case of a line parser function. This function is given a file to parse from and returns a stream of parsed tokens. The error occurs when the parser hits a line that it can’t parse. At that point, the program has a number of options, including:
(1) Cancel parsing the file all together
(2) Ignore the line and continue (maybe logging an error)
(3) Fix up the input in some way or emit a marker in the parsed token stream.
The problem with the exception model is that an exception handler in a calling function is only in the position to do (1). By the time it receives the exception the stack has been unrolled and its associated state lost. This means that if the program wants to do any of the other possibilites the exception handling implementation code needs to be in the parsing function itself, which strongly couples its behaviour with the rest of the program.
In lisp the condition handler further up the stack can do any of the 3 options, including e.g. logging the error and then invoking a ’skip-log-entry’ restart, or maybe the ‘use-value’ restart passing it a valid value to put in the token scheme.

Hmm. It seems as though there’s a danger here of leaking information outside the called method. If I call the parse file method, how do I as the caller know what to do if there’s a problem parsing the document? If I’m expected to know that, then you can just make that feature part of the API - “I’ll call you back when there’s a problem parsing the file”. Perhaps I’m missing something but I’m not sure that this doesn’t solve a problem that soluble in other ways.
Hi James,
The caller knows what to do because it has requirements it wants to fulfill. If you want a parser that silently ignores the errors you write an exception handler that invokes the ’skip-line’ restart. If you want to log you do that etc..
This problem is certainly solvable in other ways - you could implement an error callback, or maybe an abstract base class or strategy pattern or something. AFAICS the benefit of the condition system is that it’s quick and easy to do the right thing upfront - you defer the error conditions to the caller, who is more likely to know what it wants to do and can change later.
E.g. If I’m writing a parse function in python/java I don’t think ‘this should be an abstract base class because I might want to reuse it in other circumstances later’ - I just write and test the function (simplest thing).
Then when the program wants to ignore unparseable lines I might add a flag-argument to the function. Finally I might refactor it into a class structure later when I need to use it in other systems.
With conditions I just add the resume points to the function - the refactoring is small and idiomatic.
(btw, it’s early days for me and common lisp, so I don’t have any practical experience of how well this works)