screwlisp proposes kittens

ANSI cl condition report example

| link | Last. 20260125T210830473Z |

In my example illustrating that restarts and condition bindings are dynamically computed in and for the local context I was often adding printed notes.

However conditions provide :report and simple-condition provides simple-condition-format-control and simple-condition-format-arguments.

One imagining of combining these two is

(define-condition foo (simple-condition)
  ()
  (:report simple-condition-report)
  (:default-initargs :format-control
		     "With arguments ~@{~a~^, ~}"))

(defun simple-condition-report (c stream)
  (apply 'format
	 stream
	 (simple-condition-format-control c)
	 (simple-condition-format-arguments c)))

(handler-bind
    ((foo #'princ))
  (signal 'foo :format-arguments '(bar baz)))

in the repl, if you are not playing along:

CL-USER> (define-condition foo (simple-condition)
	   ()
	   (:report simple-condition-report)
	   (:default-initargs :format-control
			      "With arguments ~@{~a~^, ~}"))
FOO
CL-USER> (defun simple-condition-report (c stream)
	   (apply 'format
		  stream
		  (simple-condition-format-control c)
		  (simple-condition-format-arguments c)))
SIMPLE-CONDITION-REPORT
CL-USER> (handler-bind
	     ((foo #'princ))
	   (signal 'foo :format-arguments '(bar baz)))
With arguments BAR, BAZ
NIL

I do not want to belabor this example except to point out that ansi common lisp standardizes this mode of user interaction (a lisp user being the programmer) and it is hence provided as part of all conformant common lisp implementations.

For me, when I am writing a note like this one instead of me manually steering a mess of functions, and all the correct arguments coming out of my brain in the repl I should instead (signal 'a-need) and then steer through any ambiguities with the numpad as my controller tapping the numbers for :reports I want.

Instead of reprogramming every time (the “glue code” method), programming in terms of standardized condition handling, signalling desires then seeing and navigating reported options when an interactive choice is necessary is a portable way of making code stick.

I have a handler for this need, or if I do not there is a structured way and place to add handling such that I do not need to do it again in a subtly different context in the future, or remember everything about what I need to do.

The above uses the lisp *print-escape* mechanism

CL-USER> (make-condition 'foo :format-arguments '(1 2 3))
#<FOO "With arguments ~@{~a~^, ~}" {100215BF33}>
CL-USER> (princ *)
With arguments 1, 2, 3
#<FOO "With arguments ~@{~a~^, ~}" {100215BF33}>
CL-USER> (prin1 *)
#<FOO "With arguments ~@{~a~^, ~}" {100215BF33}>
CL-USER> 

Some hyperspec links:

screwlisp proposes kittens