Nitpick:<p>> While Common Lisp calls them “conditions”, I will stick with “error” in this post, because I don’t think “condition” is very self-explanatory if you’re not familiar with the language already. Please forgive my inaccuracy.<p>This is misleading. It is possible to signal conditions that are not errors, and therefore do not require stack unwinding, like errors do. The condition facility allows one to execute arbitrary code with arbitrary arguments at the SIGNAL site.<p>`SIGNAL` walks the list of condition handlers and executes the type-matching ones in order of their binding. If a handler returns normally, then next ones are executed; if all matching handlers are exhausted, `SIGNAL` returns, and code execution continues.<p><pre><code> CL-USER> (handler-bind ((condition (lambda (c) (format t ";; Foo: ~A~%" c)))
(condition (lambda (c) (format t ";; Bar: ~A~%" c)))
(condition (lambda (c) (format t ";; Baz: ~A~%" c))))
(signal 'condition)
42)
;; Foo: Condition CONDITION was signalled.
;; Bar: Condition CONDITION was signalled.
;; Baz: Condition CONDITION was signalled.
42
</code></pre>
Of course, a handler can perform a non-local transfer of control elsewhere, e.g. by using `GO` or `THROW`. In such a case, control is transferred out of `SIGNAL`, so next handlers are - naturally - not invoked.<p>While I understand that this post is trying to appeal to language newcomers, simplifying the whole condition system to an "error try-catch" is a drastic misrepresentation of the condition system that will leave the newbies with the impression that that's all that is possible with that feature. Since it seems that the author is a Lisp newcomer as well (which I wholeheartedly admire! :), I'd advise him to use the original notation of "condition", instead for the one of "error".
Aside from restarts, the core difference between the Common Lisp condition system and exceptions in most other languages is that the exception handler can run before the stack is unwound.<p>Having the call-stack available at the time the handler runs can be very useful; many modern dynamic languages will save some of that information in the exception object. It's still surprising to me that so very few languages have copied this feature (or even independently discovered it).
Many years ago I wrote about restarts in CL using the example of a CSV parser: <a href="https://lisper.in/restarts" rel="nofollow">https://lisper.in/restarts</a><p>Fun fact: the restarts based CSV parser was based on some real world work me and a colleague had done for an online travel portal. I wrote about it here: <a href="https://www.reddit.com/r/lisp/comments/7k85sf/a_tutorial_on_conditions_and_restarts/drceozm/" rel="nofollow">https://www.reddit.com/r/lisp/comments/7k85sf/a_tutorial_on_...</a>
I find that Practical Common Lisp has not aged well. Maybe it's the "practical" part with the specific examples the author used -that are now terribly dated- that is mainly responsible, but the end result is that I no longer recommend it.<p>My goto recommendation for newcomers is Norvig's PAIP which is full of insightful moments and unbelievably good code and for people with more experience "Let over Lambda" by Doug Hoyte, which is a mind-blowing book mainly because of the time-transcendent nature of the examples Doug chose.
In TXR Lisp, I unified condidtions and restarts into one thing: exceptions. By programmer convention only, restarts are exceptions derived from <i>restart</i>.<p>The documentation has dialect notes about this with a comparative example:<p><a href="https://www.nongnu.org/txr/txr-manpage.html#N-00F77525" rel="nofollow">https://www.nongnu.org/txr/txr-manpage.html#N-00F77525</a>
Can somebody please also elaborate what is the difference between condition system in CL and "new thing" algebraic effect handlers? On the surface I see no difference, other that the latter is being a more formalized version of conditions?
But we have same properties: 1. signal a condition to some handler(s), possibly with value. 2. reify the stack into a (delimited up to level with handler) continuation and let handler decide what to do with it: save, restart, resume with some value. Am I missing something?
A long time ago I wrote a conditions system for python: <a href="https://code.google.com/archive/p/pyconditions/" rel="nofollow">https://code.google.com/archive/p/pyconditions/</a><p>I wouldn't recommend using it, but it is an interesting error/control model, and I always wondered why it hasn't seen wider implementation - I presume because it is closer to the "dangerous" end of the power spectrum.
The condition system in Common Lisp is really amazing piece of work. Error and exception handling is just subclass of larger set of possible uses called conditions.
Interesting. This looks like an implementation of the abstract computer science notion of continuations (<a href="https://en.wikipedia.org/wiki/Continuation);" rel="nofollow">https://en.wikipedia.org/wiki/Continuation);</a> neat to see them used this way.
With a quick DuckDuckGo-ing, I found this intro to be really understandable compared to most links I read:<p><a href="https://z0ltan.wordpress.com/2016/08/06/conditions-and-restarts-in-common-lisp/" rel="nofollow">https://z0ltan.wordpress.com/2016/08/06/conditions-and-resta...</a>
R, continuing its theme of being a weird Lisp with C syntax and really bad function names, has a condition system: <a href="https://adv-r.hadley.nz/conditions.html" rel="nofollow">https://adv-r.hadley.nz/conditions.html</a>
Keep meaning to look at this, Clojure has some libraries for this I could use:<p><a href="https://github.com/clojureman/special#alternative-libraries" rel="nofollow">https://github.com/clojureman/special#alternative-libraries</a>
The author doesn't seem to understand that not all exceptional situations are errors, which suggests he is a complete newbie to exception handling, which explains why he didn't propose the word "exception" instead of "condition".