Lisp Restart Example

Could some Lisp guy put some example code for a restart here? Thanks


Um, what's a "restart" in the context of Lisp programming?

See CommonLispConditionSystem.

Also: http://www.lispworks.com/reference/HyperSpec/Body/09_adb.htm

More about 'Conditions' in Lisp: http://www.nhplace.com/kent/Papers/Condition-Handling-2001.html


In this section, we define a hashtable accessor function. Unlike normally, this one signals an error if it can't find the key you give it.

We won't write any code to inspect or handle the error, though we could; instead, the debugger is called � where you play the role of the handler. (In case you're wondering,you can always mask the debugger with whatever program you want, so some poor end-user doesn't have to be confronted with it.)

So, when the error occurs, the function offers some "restarts" � which you can see and invoke if you want. For example, one handler is "use-new-key". That one allows you to provide a new key for the function to find in the hashtable. If that key is found, the function will return normally, just as if you'd asked it to find that key in the first place. Otherwise, the error is signalled anew, this time pointing out that your new key can't be found.

Another restart is "use-new-hash". So the function tries looking for the old key again, but this time in a new hashtable. Again, if this works, everything will proceed as if nothing exceptional occurred.

And another one is simply returning from the function, with whatever default return value you had passed it earlier.

 (define-condition restartable-gethash-error (error)
   ((key  :initarg :key :accessor key)
    (hash :initarg :hash :accessor hash))
   (:report (lambda (condition stream)
              (format stream "RESTARTABLE-GETHASH error getting ~A from ~A."
                      (key condition)
                      (hash condition)))))

(defun read-new-value (what) (format t "Enter a new ~A: " what) (multiple-value-list (eval (read))))

(defun restartable-gethash (key hash &optional default) (restart-case (multiple-value-bind (value present) (gethash key hash default) (if present (values value present) (error 'restartable-gethash-error :key key :hash hash))) (continue () :report "Return not having found the value." (values default nil)) (try-again () :report "Try getting the key from the hash again." (restartable-gethash key hash)) (use-new-key (new-key) :report "Use a new key." :interactive (lambda () (read-new-value "key")) (restartable-gethash new-key hash)) (use-new-hash (new-hash) :report "Use a new hash." :interactive (lambda () (read-new-value "hash")) (restartable-gethash key new-hash))))

(defun list-hash (&rest list) (let ((hash (make-hash-table))) (loop for (key val) on list by #'cddr do (setf (gethash key hash) val)) hash))


Below is a simple interaction on the Lisp prompt, after you've loaded the above code.

 CL-USER 1 > (defparameter *fruits-and-vegetables*
               (list-hash
                  'apple   'fruit 
                  'orange  'fruit
                  'lettuce 'vegetable
                  'tomato  'depends-on-who-you-ask))
 *FRUITS-AND-VEGETABLES*

CL-USER 2 > (defparameter *computer-manufacturers* (list-hash 'pc 'ibm 'pdp-11 'dec '3600 'symbolics 'macintosh 'apple)) *COMPUTER-MANUFACTURERS*

CL-USER 3 > (restartable-gethash 'pdp-11 *computer-manufacturers*) DEC T

CL-USER 4 > (restartable-gethash '3600 *computer-manufacturers*) SYMBOLICS T

CL-USER 5 > (restartable-gethash 'orange *fruits-and-vegetables*) FRUIT T

CL-USER 6 > (restartable-gethash 'mango *fruits-and-vegetables*)

Error: RESTARTABLE-GETHASH error getting MANGO from #<EQL Hash Table{4} 10C6839F>. 1 (continue) Return not having found the value. 2 Try getting the key from the hash again. 3 Use a new key. 4 Use a new hash. 5 (abort) Return to level 0. 6 Return to top loop level 0.

Type :b for backtrace, :c <option number> to proceed, or :? for other options

CL-USER 7 : 1 > (setf (gethash 'mango *fruits-and-vegetables*) 'fruit) FRUIT

CL-USER 8 : 1 > :c 2 FRUIT T

CL-USER 9 > (restartable-gethash 'pdp-11 *fruits-and-vegetables*)

Error: RESTARTABLE-GETHASH error getting PDP-11 from #<EQL Hash Table{5} 10C6839F>. 1 (continue) Return not having found the value. 2 Try getting the key from the hash again. 3 Use a new key. 4 Use a new hash. 5 (abort) Return to level 0. 6 Return to top loop level 0.

Type :b for backtrace, :c <option number> to proceed, or :? for other options

CL-USER 10 : 1 > :c 4 Enter a new hash: *computer-manufacturers* DEC T

CL-USER 11 > (restartable-gethash 'aapl *fruits-and-vegetables*)

Error: RESTARTABLE-GETHASH error getting AAPL from #<EQL Hash Table{5} 10C6839F>. 1 (continue) Return not having found the value. 2 Try getting the key from the hash again. 3 Use a new key. 4 Use a new hash. 5 (abort) Return to level 0. 6 Return to top loop level 0.

Type :b for backtrace, :c <option number> to proceed, or :? for other options

CL-USER 12 : 1 > :c 3 Enter a new key: 'apple FRUIT T

CL-USER 13 > (restartable-gethash 'quantum-mechanics *fruits-and-vegetables*)

Error: RESTARTABLE-GETHASH error getting QUANTUM-MECHANICS from #<EQL Hash Table{5} 10C6839F>. 1 (continue) Return not having found the value. 2 Try getting the key from the hash again. 3 Use a new key. 4 Use a new hash. 5 (abort) Return to level 0. 6 Return to top loop level 0.

Type :b for backtrace, :c <option number> to proceed, or :? for other options

CL-USER 14 : 1 > :c 1 NIL NIL


CategoryLisp CategoryCommonLisp

EditText of this page (last edited May 12, 2012) or FindPage with title or text search