I've been reading the excellent book by Peter Seibel Practical Common Lisp in order to address some research I've been doing related with the Common Lisp error handling system.
Although I have read the explanation in the book and tried to dig some information in the net I have been not capable of understand the meaning and the usage of the STORE-VALUE
and USE-VALUE
restarts. Can someone explain what is the purpose of these functions?
;;; Example of the STORE-VALUE and USE-VALUE restarts
(defun careful-symbol-value (symbol)
(check-type symbol symbol)
(restart-case (if (boundp symbol)
(return-from careful-symbol-value
(symbol-value symbol))
(error 'unbound-variable
:name symbol))
(use-value (value)
:report "Specify a value to use this time."
value)
(store-value (value)
:report "Specify a value to store and use in the future."
(setf (symbol-value symbol) value))))
Here is an example in Lispworks.
Let's define a class foo
with a slot bar
.
CL-USER 26 > (defclass foo () (bar))
#<STANDARD-CLASS FOO 4020001723>
We need an instance:
CL-USER 27 > (make-instance 'foo)
#<FOO 402000339B>
Now we try to access the unbound slot of that object. Note that *
accesses the result of the previous evaluation.
CL-USER 28 > (slot-value * 'bar)
We are getting an error and a bunch of restarts:
Error: The slot BAR is unbound in the object #<FOO 402000339B>
(an instance of class #<STANDARD-CLASS FOO 4020001723>).
1 (continue) Try reading slot BAR again.
2 Specify a value to use this time for slot BAR.
3 Specify a value to set slot BAR to.
4 (abort) Return to level 0.
5 Return to top loop level 0.
Type :b for backtrace or :c <option number> to proceed.
Type :bug-form "<subject>" for a bug report template or :? for other options.
Number 2 is a use-value restart and number 3 is a store-value restart.
Let's get the list of restarts:
CL-USER 29 : 1 > (compute-restarts)
(#<RESTART ABORT 4020009EB3> #<RESTART ABORT 4020009F53>
#<RESTART NIL 402000585B> #<RESTART USE-VALUE 40200058DB>
#<RESTART STORE-VALUE 402000595B> #<RESTART ABORT 40200059DB>
#<RESTART ABORT 4020005A7B> #<RESTART ABORT 41700D2503>)
In LispWorks we can get the current condition object with :cc
.
CL-USER 30 : 1 > :cc
#<UNBOUND-SLOT 40200056F3>
Find the restart:
CL-USER 31 : 1 > (find-restart 'store-value *)
#<RESTART STORE-VALUE 402000595B>
Let's print it:
CL-USER 32 : 1 > (princ *)
Specify a value to set slot BAR to.
#<RESTART STORE-VALUE 402000595B>
Also for the use-value
restart:
CL-USER 33 : 1 > :cc
#<UNBOUND-SLOT 402000B293>
CL-USER 34 : 1 > (find-restart 'use-value *)
#<RESTART USE-VALUE 402000B47B>
CL-USER 35 : 1 > (princ *)
Specify a value to use this time for slot BAR.
#<RESTART USE-VALUE 402000B47B>