[Lispweb] small issue in get-multipart-header
Steve Haflich
smh at franz.com
Wed Feb 22 17:02:14 CST 2006
From: Kamen TOMOV <kamen at evrocom.net>
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?
Well, only documentation and source reading can reveal what the code
_might_ signal, but you can easily see what it actually does signal on
any particular execution. You can't do it with handler-case because
when a handler-case clause is executed it has already thrown out of
the protected code body. (See the ANS pages for handler-case and
handler-bind where is this explained pretty well). But you can
examine signals promiscuously using handler-bind, provided your
handler(s) don't actually "handle" the signals by making a nonlocal
exit. Here's a minimal demonstration:
cl-user(40): (handler-bind ((t #'describe)) (warn "Pie") pi)
#<simple-warning @ #x1001f0e172> is an instance of #<standard-class simple-warning>:
The following slots have :instance allocation:
format-control "~1@<Pie~:@>"
format-arguments nil
plist nil
#<excl::advance-warning @ #x1000258f92> is an instance of #<standard-class excl::advance-warning>:
The following slots have :instance allocation:
format-control <unbound>
format-arguments nil
plist nil
Warning: Pie
3.141592653589793d0
cl-user(41):
For example can I find out (with programming means) what kind of
signals this form (get-multipart-header req) can throw?
You've missed the point entirely! It is none of your business whether
some body of code signals any conditions that are disjoint with the
documented set of condition classes (error, warn, any implementration
extensions) because they are the implementation's machinery. In some
fanciful implementation the cdr function might compute addresses using
floating point arithmetic. That's why you are not allowed to redefine
or overload internal implementation functions. Similarly, you are not
allowed to mess with unexported condition classes.
You have good reason for wanting to know the full set of subclasses of
the cl:error condition, and perhaps also cl:warning. (Some people
might consider the required transitive specification of exceptions in
Java code a positive feature of the language. Or perhaps not, but it
does seem to make Java programmers more sensitive to considering and
classifying exceptions while we Lisp programmers seem to do it only as
a casual afterthought.) But if you need to know, or even think you
need to know, about other condition classes that are disjoint from
these, and not a documented part of siome subprogram interface, then
something is wrong.
You may have noticed the excl::advance-warning condition signalled
above. The cl:warn in ACL first signals the normal warning, and if no
one handles it (typically with muffle-warning) it signals an
excl::advance-warning condition. Programs like the file compiler use
this to print those nice "While compiling function foo in file bar"
messages without having to print functions that geenrate no warnings,
and without the wasting stream real estate if multiple warnings occur
within a single function. There is a handler bind around the file
compiler suppressing the "While compiling" message if the file and
function are the same as the previous announcemen.
The point of this condition class is that since it is disjoint from
all documented condition classes except condition itself, no other
code should ever notice it (because signal of an unhandled condition
class is a nop) and certainly no other code should handle it. There
is no need to document that this machinery is being used by the
compiler any more than it is necessary to document whether the
compiler uses bit vectors.
As for get-multipart-header, it probably signals a variety of error
subclasses. Do you need to categorize them further? For that you
might need to read the code, and even so, specific errors signalled by
routines called by that code could still be missed. This is one
aspect of Java that is arguably superior, although in practice most
code just handles generic errors by transfering to some outer restart
point.
More information about the lispweb
mailing list