exceptionerror-handlinglispcommon-lispcondition-system

Semantics of the 'store-value' and 'use-value' restarts in the Common Lisp error handling system


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))))

Solution

  • 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>