Show HN: My book, The Common Lisp Condition System (amazon.com)
recommended by 2 users | 2020 | 177 points by phoe-krk | lisp | original thread |
2 users recommended this thread. What they said:
dannyobrien Apr 22, 2022 | on: Common Lisp Resources | context

The one that sticks out for me is condition handling, particularly restarts. I'm someone who reads books about programming more than I actually program, so I don't know how actually practical Lisp's ability to do extremely sophisticated responses to error conditions and the like (including choosing where to throw to programmatically at the error site) is. It strikes me that it might be one of those things -- like hot-reloading -- where there are so many factors that it's mostly impossible for humans to get right. But!! I've never seen it in any other language, and I think about it a lot.

@phoe-krk's book on it, https://news.ycombinator.com/item?id=24867548 is very good.

rauhl Jul 3, 2025 | on: The story of Max, a real programmer | context

Have you seen Common Lisp’s condition system? It’s a step above exceptions, because one can signal a condition in low-level code, handle it in high-level code and then resume back at the lower level, or anywhere in between which has established a restart.

https://gigamonkeys.com/book/beyond-exception-handling-condi... is a nice introduction; https://news.ycombinator.com/item?id=24867548 points to a great book about it. I believe that Smalltalk ended up using a similar system, too.

> It would need to be the case that code that doesn’t want to handle errors (like Max’s simple website) doesn’t have any error handling code, but it’s easy to add, and common patterns (e.g. “retry this inner operation N times, maybe with back off and jitter, and then fail this outer operation, either exiting the program or leaving unaffected parts running”) are easy to express

Lisp’s condition system can handle that! Here’s a dumb function which signals a continuable error when i ≤ 3:

    (defun foo ()       (loop for i from 0             do (if (> i 3)                    (return (format nil "good i: ~d" i))                    (cerror "Keep going." "~d is too low" i)))) 

If one runs (foo) by hand then i starts at 0 and FOO signals an error; the debugger will include the option to continue, then i is 1 and FOO signals another error and one may choose to continue. That’s good for interactive use, but kind of a pain in a program. Fortunately, there are ways to retry, and to even ignore errors completely.

If one wishes to retry up to six times, one can bind a handler which invokes the CONTINUE restart:

    (let ((j 0))       (handler-bind ((error #'(lambda (c)            (declare (ignore c))            ;; only retry six times            (unless (> (incf j) 6)              (invoke-restart 'continue)))))         (foo))) 

If one wants to ignore errors, then (ignore-errors (foo)) will run and handle the error by returning two values: NIL and the first error.