3

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))))
Rainer Joswig
  • 136,269
  • 10
  • 221
  • 346
Paulo Tomé
  • 1,910
  • 3
  • 18
  • 27

2 Answers2

7

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>
Rainer Joswig
  • 136,269
  • 10
  • 221
  • 346
0

Perhaps a very simplistic explanation: use-value will use the value you give it only once, and the next time you hit the same place, it will error again. store-value will only ask you once for correction.

Imagine the situation: you are iterating over an array, and in some place you mistyped the index variable, say, j instead of i. If you choose to use-value once you hit the non-existing variable, it will keep asking you until the end of the loop. But if you choose to store-value, then it will try to use whatever you gave it and if it worked, will continue silently until the end of the loop.

  • 2
    Not a very good example, because `store-value` will assign `j`, but the iteration updates `i`. The errors will stop, but it will use the same value each time through the loop, rather than the loop index. – Barmar May 26 '13 at 22:04