Newsgroups: comp.lang.lisp
From: markt@dgp.toronto.edu (Mark A. Tapia)
Subject: Re: CL condition system
Organization: CSRI, University of Toronto
Date: 13 Oct 92 18:10:25 GMT

In article <1992Oct11.185718.26184@ils.nwu.edu> dmerrill@ils.nwu.edu (Douglas C. Merrill) writes:
>So, for example, say I wanted to prevent division-by-zero errors, and
>flag the bad 
>operand for the student.  Here is the code that i thought would do so:
>(defun foo (arg)
>  (handler-case (eval arg)
>    (division-by-zero (condition) 
>      (format t "~A Args are ~A" condition (arithmetic-error-operands
>condition)))))
>
>However, this code returns
>    ? (foo '(/ 3 0))
>    Can't divide by zero. Args are NIL
>
>What am I doing wrong?  How do I access the erroneous operand.
>
>I also am confused about why sometimes the operand is part of the
>condition 
>message, and other times is not.  For example,
>(defun farg (arg)
>   (handler-case (eval arg)
>      (unbound-variable (condition) (format t "~A" condition))))
>returns
>      ? (farg '(+ a 1))
>     Unbound variable: A
>
>Can anyone explain why the argument is sometimes present by default and
>sometimes 
>not and how to access the arg if it is not put in the message
>automatically?  (BTW -- I use 
>MCL 2.0)


For a division by zero condition, the erroneous operand is always 0.
There are no arithmetic-error-operands for this condition.

You cannot access the actual arithmetic operands for the following
conditions:
   division-by-zero
   floating-point-overflow
   floating-point-underflow

You could rewrite the handler:
(defun foo (arg)
  (handler-case (eval arg)
    (arithmetic-error (condition)
                      (if (arithmetic-error-operands condition)
                        (format t "~A Args are ~A" condition (arithmetic-error-operands
                                                              condition))
                        (format t "~A" condition)))))
?(foo '(/ 1 0))
Can't divide by zero.
NIL

(defun foo (arg)
  (handler-case (eval arg)
       (division-by-zero (condition) condition)))
? (setq cond  (foo '(/ 1 0)))
#<DIVISION-BY-ZERO #x484039>
? (format t "~a" cond)
Can't divide by zero.
? (arithmetic-error-operands cond)
nil 

Since division by-zero is a subtype of arithmetic error,
place the division-by-zero condition before the arithmetic-error condition
otherwise the arithmetic-error condition to be invoked for a division-by-zero
error.

(defun foo1 (arg)
  (handler-case (eval arg)
    (division-by-zero ()
                      (format t "You tried to divide by 0."))
    (arithmetic-error (condition)
                      (if (simple-condition-format-arguments condition)
                        (format t
                                (simple-condition-format-string condition)
                                (simple-condition-format-arguments condition))
                        (format t
                                (simple-condition-format-string condition))))
    (condition (condition)
               condition)))

Here are some tests of using foo1

? (foo1 '(/ 1 0))
You tried to divide by 0.
NIL

? (foo1 '(* 2 most-positive-long-float))
Floating point overflow
NIL
? (makunbound 'a)
a
? (foo1 '(/ 1 a))
#<UNBOUND-VARIABLE #x4872E1>
Newsgroups: comp.lang.lisp