[Lispweb] small issue in get-multipart-header

Kamen TOMOV kamen at evrocom.net
Wed Feb 22 15:58:16 CST 2006


On Tue, Feb 21 2006, Steve Haflich wrote:

>    CL-USER> (handler-case t (t ()))
>    T
>    
> This isn't directly a comment on the original question, but this
> handler-case is not good CL style, and may even be dangerously so.
>
> It is customary to think of the condition system as having to do
> with errors and warnings, but it was carefully defined to be a
> general facility in the execution model.  The handler-case form
> above handles _any_ otherwise-unhandled condition signalled within
> the execution of the expression.  It is a really poor idea to handle
> conditions promiscuously, that is, to handle condition types about
> which you know nothing and about whose existence you might not even
> be aware.  The implementation or some other loaded module
> independent of your code might use some condition subclass disjoint
> from any of the public condition classes in order to serve some
> private communication need.  Code like the above could break that
> code in was hard to debug, and perhaps even hard to detect.

I agree.

Now that mention it, I wonder what is the proper way to find out what
kind of signals throws a particular black-boxed function without
studying its code? 

For example can I find out (with programming means) what kind of
signals this form (get-multipart-header req) can throw? 

Although, I generally agree that forms like this one:

(handler-case (some-call some-params)
              (t () something))

are bad, there are certain cases where a program should deal with a
problem quetly.

> It is possible, for instance, that a mp threading system could use
> signals behind the programmer's back, or signals could even be used
> to handle the first reference to a particular dynamic variable on a
> new thread.  A defsys facility might signal conditions to
> communicate upward information about actions it takes building
> subsystems.  I know of no implementations that do any of these
> things, but someday there could be, and it is unwise to write code
> that is gratuitously incompatible.
>
> The moral is that CL code should handle only publically documented
> condition classes that have a well-established meaning, such as
> error and warning, or conditions that the code defines itself and
> which are otherwise disjoint subclasses only of the class condition
> itself.

Often there isn't such documentation. For example:
get-multipart-header

>
> The following shows a silly use of signals that is not transparent to
> the promiscuous handler-case:
>
> cl-user(3): (define-condition tuesday () ())
> tuesday
> cl-user(4): (defparameter *tuesday* (make-condition 'tuesday))
> *tuesday*
> cl-user(5): (defun tuesdayp ()
> 	      (= 1 (nth-value 6 (decode-universal-time (get-universal-time)))))
> tuesdayp
> cl-user(6): (defun my-random (n)
>               ;; Let monitors know if we are called on a Tuesday.
> 	      (when (tuesdayp) (signal *tuesday*))
> 	      (random n))
> my-random
> cl-user(7): (handler-case (my-random 100)
> 	      (t nil))
> nil
> cl-user(8): (handler-case (random 100)
> 	      (t nil))
> 21

Yeah, it's not pretty.

-- 
Kamen TOMOV



More information about the lispweb mailing list