From: Adam Carlson
Subject: Automatic restarts in lisp
Date: 
Message-ID: <29fhr4INNoon@ymir.cs.umass.edu>
I know this is a no-no, but since I don't read this group regularly, please
respond via email to ·······@cs.umass.edu

I would like to handle an error without having a non-local goto that breaks the
normal flow of control in my program.  In particular, I'd like to have a macro
that watches for floating-point-underflow errors and returns a zero from the
frame which produced the error.  Furthermore, I need to do this in common lisp,
because it's for a program which needs to run under multiple platforms.  (In
explorer common lisp, condition-bind does what I want.)

For example

;;; This will produce a floating-point underflow on most machines

(defun produce-error ()
  (exp -1000))


(defmacro with-floating-point-underflow-to-zero (&body body)
	...)

(defun foo ()
   (with-floating-point-underflow-to-zero
      (+ 1 (produce-error))))

(foo) => 1 

If I implement the macro with handler-case or restart-case/handler-bind then when
exp signals an underflow error, the entire body is aborted and the handler
returns 0.

For example

(defun test-error-handler-1 ()
    (handler-case 
	(+ 1 (produce-error))
      (floating-point-underflow (condition)
	(values 0.0))))

and

(defun test-error-handler-2 ()
   (restart-case (handler-bind
		    ((floating-point-underflow #'(lambda (condition)
						    (declare (ignore condition))
						    (use-value 0.0))))
		   (+ 1 (produce-error)))
      (use-value (value)
	value)))

will both return 0.0, not 1 because when the error is signaled, the
floating-point-underflow handler will be called and return its value and even
though the stack contains a frame for the + function call, the handler will jump
out of the form it is evaluating and into the appropriate restart, leaving the
rest of the form unevaluated.

One solution is to wrap the macro around as tight a piece of code as possible,
but this is unreasonable because in the worst case my code will have a handler
wrapped around every arithmetic expression and the average case for this code
won't be much better.  What I would like is a macro I can wrap around a large
body of code, and wherever the error(s) occur in the body, they get replaced with
0.  This seems doable, since in many versions of lisp, when an error of this type
occurs, one of the restarts is "Supply a different value."  I would like to have
that type of behaviour, but without the interactive aspect.  Rather than falling
into the debugger and asking the user for a new value, I would just like to
continue with a predefined handler function (in this case, one that returns 0).

Adam Carlson
·······@cs.umass.edu