I owe you this article after [last week's Lispy Gopher Climate Tuesday Night In The Americas](https://communitymedia.video/w/uxcaFqra6buSK955zsuUog) where [Kent Pitman](https://nhplace.com/kent) pointed out two improvements to [my note on common lisp condition signalling, handling and restarting](/fundamental/nested-ansi-cl-conditions/). Lisp condition handling restarts are local continuations, i.e. a dynamically computed available restart is done from the location the condition was signalled rather than from a lexically scoped preordained point.

Until now, my original example had been like this:

```
(define-condition foo () ())
(define-condition bar () ())

(defun has-a-bar->buz (c)
  (declare (ignore c))
  (restart-case
      (handler-bind
	  ((bar #'(lambda (c) (invoke-restart (find-restart 'buz) c))))
	(restart-case
	    (signal 'bar)
	  (buz (c) (declare (ignore c))
	    (print "inner buz reached")
	    (print (compute-restarts))
	    (let ((r (find-restart 'buz)))
	      (print r)
	      (invoke-restart r c)))))))

(restart-case
    (handler-bind
	((foo #'has-a-bar->buz)
	 (foo #'(lambda (c)
		  (invoke-restart (find-restart 'baz) c)))
	 (bar #'(lambda (c)
		  (invoke-restart (find-restart 'buz) c))))
      (signal 'foo))
  (baz (c) (declare (ignore c)) (print "baz reached") nil)
  (buz (c) (declare (ignore c)) (print "buz reached") nil))
```

Kent's two improvements were to generally use the condition optional argument when using `find-restart`:

```
(find-restart 'baz c)
```
for the condition `c`. This is important because while handling a condition, a second condition could be signalled. Then, the two conditions can and probably will have different computed restarts available to them. So when finding a local restart by name, in general do specify the condition you want to do the restart for. `find-restart` will compute and return the restart (again, local continuation) of that name, specifically the one available to the optional condition argument if it is specified.

Which brings us to Kent's second point, that `find-restart` returns `nil` if no applicable restart is found, and I was calling `invoke-restart` on a value that might be a `restart` or might be `nil` and `invoke-restart` only takes `restart`s.

```
CL-USER> (invoke-restart nil)
The value
  NIL
is not of type
  (OR (AND SYMBOL (NOT NULL)) RESTART)
when binding RESTART
   [Condition of type TYPE-ERROR]
```

> A helpful e.g. tone correction here 20260204T045621070Z

Kent noted it is possible to assure the restart is always there, so that error checking is a mere formality. But if you're wrong, you'll get a common lisp type-error signalled when find-restart returns NIL (fails to find an applicable restart). More commonly you want the condition handler to decline (return without restarting) in that case, allowing the next handler to handle (or decline) the condition, so you want to just notice the NIL returned from find-restart and not pass it uselessly through to invoke-restart.

In other words, normally a handler should decline a condition (errors are one example of conditions) that it cannot handle (provide a local restart continuation from) allowing the next handler to accept or decline a condition. Only in particular scenarios should the unavailability of a restart to one handler signal a type error condition of its own.

Rewriting,

```
(define-condition foo () ())
(define-condition bar () ())

(defun has-a-bar->buz (c)
  (declare (ignore c))
  (restart-case
      (handler-bind
	  ((bar #'(lambda (c)
		    (let ((r (find-restart 'buz c)))
		      (when r
			(invoke-restart r c))))))
	(restart-case
	    (signal 'bar)
	  (buz (c)
	    (print "inner buz reached")
	    (print (compute-restarts))
	    (let ((r (find-restart 'buz c)))
	      (print r)
	      (when r
		(invoke-restart r c))))))))

(restart-case
    (handler-bind
	((foo #'has-a-bar->buz)
	 (foo #'(lambda (c)
		  (let ((r (find-restart 'baz c)))
		    (when r
		      (invoke-restart r c)))))
	 (bar #'(lambda (c)
		  (let ((r (find-restart 'buz c)))
		    (when r
		      (invoke-restart r c))))))
      (signal 'foo))
  (baz (c) (declare (ignore c)) (print "baz reached") nil)
  (buz (c) (declare (ignore c)) (print "buz reached") nil))
```

which works the same in this case, but now the `find-restart` is more specific which is better style, and the handlers would decline (the general case) rather than signal an error condition if they did not have a restart. I am also utilising the conditions I am passing along with `invoke-restart` rather than just ignoring them in more cases. (Also, `invoke-restart` actually passes arbitrary additional arguments to the `restart` being invoked, not just conditions specifically).

```
CL-USER> (define-condition foo () ())
(define-condition bar () ())

(defun has-a-bar->buz (c)
  (declare (ignore c))
  (restart-case
      (handler-bind
	  ((bar #'(lambda (c)
		    (let ((r (find-restart 'buz c)))
		      (when r
			(invoke-restart r c))))))
	(restart-case
	    (signal 'bar)
	  (buz (c)
	    (print "inner buz reached")
	    (print (compute-restarts))
	    (let ((r (find-restart 'buz c)))
	      (print r)
	      (when r
		(invoke-restart r c))))))))

HAS-A-BAR->BUZ
CL-USER> (restart-case
    (handler-bind
	((foo #'has-a-bar->buz)
	 (foo #'(lambda (c)
		  (let ((r (find-restart 'baz c)))
		    (when r
		      (invoke-restart r c)))))
	 (bar #'(lambda (c)
		  (let ((r (find-restart 'buz c)))
		    (when r
		      (invoke-restart r c))))))
      (signal 'foo))
  (baz (c) (declare (ignore c)) (print "baz reached") nil)
  (buz (c) (declare (ignore c)) (print "buz reached") nil))

"inner buz reached" 
(#<RESTART BAZ {7F8914836A23}> #<RESTART BUZ {7F89148369E3}>
 #<RESTART SWANK::RETRY {7F8914836D53}> #<RESTART ABORT {7F89148370C3}>
 #<RESTART ABORT {7F8914837AF3}>) 
#<RESTART BUZ {7F89148369E3}> 
"buz reached" 
NIL
```

A more general note was that because available local restarts from signalled conditions are computed and not lexical, it is important style *not to* use restarts and condition handling as though they had been lexical which would be misleading.

This lisp thought-leadership is a challenge because basically everyone else (such as python or java) *just has* lexically scoped error handling rather than lisp's dynamically computed local restart continuations from signalled conditions (errors are a subgroup of conditions).

We should embrace [lisp's condition system](https://www.lispworks.com/documentation/HyperSpec/Body/09_a.htm)

>to think previously impossible thoughts

to repeat Dijkstra's phrase on lisp.