Can someone explain to me have to pass a parameter to the error system?
I'm loading a font and if the font is invalid or not found, I want to
report an error. (I have this working with handler-bind). However,
I would like to show the user what he/she was using for a font name.
I can't seem to find any way to pass the name of the font on to the
handler function. I know this must be possible...
You could just create your own condition code:
(define-condition missing-font (error)
((font-name :initarg :face :reader missing-font-face))
(:report
(lambda (condition stream)
(format "Missing font: ~A" (missing-font-face condition)))))
Now, somewhere in your code you can just use make-condition to raise an
error:
(error (make-condition 'missing-font "courier"))
Inside your main code, use handler-case to get the missing-font error
condition and then you can display it to the end-user with
(missing-font-face condition). I'm sure there are other ways, too, but
this was just the first that came to mind.
Jeff M.
On 6 Oct 2005 14:44:04 -0700, "Jeff M." <·······@gmail.com> wrote:
> You could just create your own condition code:
>
> (define-condition missing-font (error)
> ((font-name :initarg :face :reader missing-font-face))
> (:report
> (lambda (condition stream)
> (format "Missing font: ~A" (missing-font-face condition)))))
>
> Now, somewhere in your code you can just use make-condition to raise an
> error:
>
> (error (make-condition 'missing-font "courier"))
(error (make-condition 'missing-font :face "courier"))
--
Lisp is not dead, it just smells funny.
Real email: (replace (subseq ·········@agharta.de" 5) "edi")
Am 06.10.2005 23:44 Uhr schrieb "Jeff M." unter <·······@gmail.com> in
························@f14g2000cwb.googlegroups.com:
> You could just create your own condition code:
>
> (define-condition missing-font (error)
> ((font-name :initarg :face :reader missing-font-face))
> (:report
> (lambda (condition stream)
> (format "Missing font: ~A" (missing-font-face condition)))))
>
> Now, somewhere in your code you can just use make-condition to raise an
> error:
>
> (error (make-condition 'missing-font "courier"))
>
> Inside your main code, use handler-case to get the missing-font error
> condition and then you can display it to the end-user with
> (missing-font-face condition). I'm sure there are other ways, too, but
> this was just the first that came to mind.
>
> Jeff M.
>
Sometimes it would be useful to test code before posting it to c.l.l. ;-)
; stream was missing in format call
(define-condition missing-font (error)
((font-name :initarg :face :reader missing-font-face))
(:report
(lambda (condition stream)
(format stream "Missing font: ~A" (missing-font-face condition)))))
; needs a keyword arg
(error (make-condition 'missing-font :face "courier"))
; actually error can be called directly with the condition symbol and args:
(error 'missing-font :face "courier")
Some of us are posting from a place where we don't a Lisp compiler on
hand. It never ceases to amaze me the number of smart people on this
newsgroup that enjoy pointing out the mistakes of others.
However, the last point (using error without a make-condition) is
something I didn't know. Thanks. :-)
Jeff M.
"Jeff M." <·······@gmail.com> writes:
> Some of us are posting from a place where we don't a Lisp compiler on
> hand. It never ceases to amaze me the number of smart people on this
> newsgroup that enjoy pointing out the mistakes of others.
>
> However, the last point (using error without a make-condition) is
> something I didn't know. Thanks. :-)
>
> Jeff M.
Some of us are posting from a place where we don't HAVE a Lisp compiler on
sorry I just wanted to be smart..
Am 07.10.2005 2:27 Uhr schrieb "Jeff M." unter <·······@gmail.com> in
························@o13g2000cwo.googlegroups.com:
> Some of us are posting from a place where we don't a Lisp compiler on
> hand.
Personally I like to use Lisp in places where there is no Usenet on hand.
;-)
> It never ceases to amaze me the number of smart people on this
> newsgroup that enjoy pointing out the mistakes of others.
Did you see the smiley? Most of us have posted code with errors sometimes.
Still I think it is good practice to mention when posted code is not tested.
(I've seen this a lot of time and it always helps me to adjust my
expectations. ;-) ) It is even better practice to post tested code. It shows
respect for the other (possibly new Lisp user) readers not to
let them struggle with own lack of concentration/time/... . (Usual
disclaimer here...)
> However, the last point (using error without a make-condition) is
> something I didn't know. Thanks. :-)
>
> Jeff M.
>
Just remember that ERROR either takes format strings (with args) or
condition types (with args). The machinery behind it seems to be well
thought out. ;-)
Rainer Joswig
"Jeff M." <·······@gmail.com> wrote:
> Some of us are posting from a place where we don't a Lisp compiler on
> hand. It never ceases to amaze me the number of smart people on this
> newsgroup that enjoy pointing out the mistakes of others.
You missed "have" from the first line :-)
I suffered from this kind of nitpicking myself a while ago. Good, isn't it:
Me: "Plaese help me understand [x|y|z]."
c.l.l illuminatus: "You mis-typed 'please'. Moron!"
Me: "..."
Remember, c.l.l has the USENET nature.
J
>
> However, the last point (using error without a make-condition) is
> something I didn't know. Thanks. :-)
>
> Jeff M.
>
Thanks for all the help, but, unfortunately nothing you gave me worked.
I've solved the problem with the following code:
(defun missing-font-error (font-name)
<report error - showing erroneous name>
in my code...
(handler-bind ((error (missing-font-error font-name)))
(setf font (xlib:open-font *display* font-name)))
This may be terrible Lisp, but it answers the probelm. Error could be
changed to the various xlib error conditions on opening a font. I
tried about every combination and it either wouldn't compile or crashed
at run time with the normal Xlib Name-Error.
I'm new to Lisp and have a LOT to learn, but I am blown away by the
simplicty of the code (once you figure it out) and the power. Do you
know how many lines of C it would take to do the above....
Thanks again. This site is a great help.
Bill
When I ran the code offers by the group I got compile errors on either
the font-name or the condition name
In article <························@o13g2000cwo.googlegroups.com>,
"WoodHacker" <·······@comcast.net> wrote:
> Thanks for all the help, but, unfortunately nothing you gave me worked.
You didn't provide much in the way of specifics in your original post.
The responders all assumed you had some measure of control over the
condition being signalled, not that you were handling an error being
reported by a preexisting library. In the latter case you're dependent
on the library designer providing the slots you want in the condition.
> I've solved the problem with the following code:
>
> (defun missing-font-error (font-name)
> <report error - showing erroneous name>
>
> in my code...
>
> (handler-bind ((error (missing-font-error font-name)))
> (setf font (xlib:open-font *display* font-name)))
>
> This may be terrible Lisp, but it answers the probelm. Error could be
> changed to the various xlib error conditions on opening a font. I
> tried about every combination and it either wouldn't compile or crashed
> at run time with the normal Xlib Name-Error.
The CLX manual I just checked mentions XLIB:FONT-ERROR, but that's a
subtype of XLIB:RESOURCE-ERROR, so it's for objects that have already
been assigned a resource ID. Since a font doesn't get an ID unless
OPEN-FONT is successful, this isn't the right condition.
So NAME-ERROR seems to be the most specific condition when the font name
can't be found. Unfortunately, as far as I can tell from the CLX
manual, NAME-ERROR doesn't have a slot that identifies the bad font name.
--
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
I still can't get this to work and I'm more confused than ever.
Clearly, I have no idea what I'm doing. If I use the following code
(handler-bind ((error '(missing-font-error font-name))
(setf font (xlib:open-font *display*
font-name)))
and use a font that I know exists, the font is loaded. However, if I
put in a bogus font I get a runtime type error. It tells me
"missing-font-error" is not a function. If I remove the quote it
gives me the proper error. However, in this case it ALWAYS gives me
the error even when the font is openable. Shouldn't it be working
this way: handler-bind checks the form. If the form fails it looks at
it's error list - in this case any error will do - and calls the
function listed for that error? All I want to do is trap the
condition where a font can't be opened and tell the user which font
can't be opened - for whatever reason. The error you get from SBCL
for an open-font failure is incomprehensable to the average user.
In article <·······················@f14g2000cwb.googlegroups.com>,
"WoodHacker" <·······@comcast.net> wrote:
> I still can't get this to work and I'm more confused than ever.
> Clearly, I have no idea what I'm doing. If I use the following code
>
> (handler-bind ((error '(missing-font-error font-name))
> (setf font (xlib:open-font *display*
> font-name)))
Look up the documentation for the function ERROR.
http://www.lisp.org/HyperSpec/Body/fun_error.html
http://www.lisp.org/HyperSpec/Body/sec_9-1-2-1.html
What are its arguments?
Either a symbol or a string or a condition object.
You have a list as argument. That's wrong.
If you have a condition type with FONT-NAME as a slot,
I would change it to:
(error 'missing-font-error :font-name font-name)
If you just want to put out a simple error message:
(error "The font named ~a is missing!" font-name)
>
> and use a font that I know exists, the font is loaded. However, if I
> put in a bogus font I get a runtime type error. It tells me
> "missing-font-error" is not a function. If I remove the quote it
> gives me the proper error. However, in this case it ALWAYS gives me
> the error even when the font is openable. Shouldn't it be working
> this way: handler-bind checks the form. If the form fails it looks at
> it's error list - in this case any error will do - and calls the
> function listed for that error? All I want to do is trap the
> condition where a font can't be opened and tell the user which font
> can't be opened - for whatever reason. The error you get from SBCL
> for an open-font failure is incomprehensable to the average user.
Thank you very much. Your code works as expected with only a minor
problem with what I will call 'transitions'. If I force an error by
calling an non-existant font, I get the proper error.
However, when I then call a good font, I get a font error - not the one
I'm reporting. This goes away by recompiling everything - which leads
me to believe the problem is with SBCL somehow, but that's a completely
different issue. The code now does exactly what I want.
This turned out to be a very interesting problem as you can see by the
number of responders. However, most people missed the point, which was
pobably my fault for not explaining it correctly.
Handler-case/handler-bind was the only way to trap the error since I
had no way to test for the error on my own. Also, there was no way to
trap the font name in a condition (that I could find to work). Your
solution allowed me to trap the error and report it correctly. Again,
thanks.
I've written code in about every popular language over the years from
Cobol to C to Java to Python to Ruby. I've never found one that
impresses me as much as CL. Where have you guys been hiding this
thing? This is great stuff....
"WoodHacker" <·······@comcast.net> writes:
> I've written code in about every popular language over the years from
> Cobol to C to Java to Python to Ruby. I've never found one that
> impresses me as much as CL. Where have you guys been hiding this
> thing? This is great stuff....
We hide it behind piles of parenthesis. That scares off most people.
Joe Marshall wrote:
> HANDLER-CASE is a macro that is intended to work similarly to the
> TRY/CATCH clauses in traditional languages.
I _know_ you know this Joe, and I don't want to beat on your case,
but newbies may get the wrong idea. HANDLER-CASE predates the
similar constructs in "traditional" languages by 20 years or so.
You must be using a nontraditional meaning for the word
"traditional".
In 1966 PL/I had a construct that was essentially a condition
handler. But a condition was not a first-class object...
"Steven M. Haflich" <···@alum.mit.edu> writes:
> Joe Marshall wrote:
>
>> HANDLER-CASE is a macro that is intended to work similarly to the
>> TRY/CATCH clauses in traditional languages.
>
> I _know_ you know this Joe, and I don't want to beat on your case,
> but newbies may get the wrong idea. HANDLER-CASE predates the
> similar constructs in "traditional" languages by 20 years or so.
> You must be using a nontraditional meaning for the word
> "traditional".
Yeah, I was trying to be generous.
HANDLER-CASE is similar to the TRY/CATCH construct that you see in
those languages that finally got around to realizing that not everyone
is going to be checking ERRNO after each and every call.
There's a long tradition of re-inventing constructs that were in Lisp
decades ago.
Joe Marshall <·········@alum.mit.edu> writes:
> There's a long tradition of re-inventing constructs that were in Lisp
> decades ago.
... often greenspunning them in the process. For example, I get the
feeling of Common Lisp being rediscovered when I look at Python or
Ruby. (Though they are nice enough compared to the mainstream
competition.)
Best,
Thomas
--
Thomas Lindgren
"It's becoming popular? It must be in decline." -- Isaiah Berlin
In article <··················@newssvr21.news.prodigy.com>,
"Steven M. Haflich" <···@alum.mit.edu> wrote:
> Joe Marshall wrote:
>
> > HANDLER-CASE is a macro that is intended to work similarly to the
> > TRY/CATCH clauses in traditional languages.
>
> I _know_ you know this Joe, and I don't want to beat on your case,
> but newbies may get the wrong idea. HANDLER-CASE predates the
> similar constructs in "traditional" languages by 20 years or so.
Hmm, Common Lisp is only about 20 years old now. So anything that it
predates by 20 years is something being developed as we speak.
> You must be using a nontraditional meaning for the word
> "traditional".
I think it's similar to the error handling mechanisms that are in CLU
and Ada, both designed before Common Lisp. Most languages with
error-handling mechanisms use termination semantics like HANDLER-CASE.
--
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
Barry Margolin <······@alum.mit.edu> writes:
> In article <··················@newssvr21.news.prodigy.com>,
> "Steven M. Haflich" <···@alum.mit.edu> wrote:
>
> > Joe Marshall wrote:
> >
> > > HANDLER-CASE is a macro that is intended to work similarly to the
> > > TRY/CATCH clauses in traditional languages.
> >
> > I _know_ you know this Joe, and I don't want to beat on your case,
> > but newbies may get the wrong idea. HANDLER-CASE predates the
> > similar constructs in "traditional" languages by 20 years or so.
>
> Hmm, Common Lisp is only about 20 years old now. So anything that it
> predates by 20 years is something being developed as we speak.
Common Lisp is a standardization of a Lisp, based almost entirely on
the dialect that had these kinds of error handling in the early 1970s.
To get more specific, the sophisticated object-oriented features date
from the late 1970s. HANDLER-BIND et al. is a refinement of CONDITION-BIND.
CONDITION-BIND was in Lisp by at least 1979. Common Lisp refined and
improved the protocol to make it a little simpler and conceptually
clearer. (Also, in the pre-CL version of the protocol, condition
objects were instances in the object-oriented language that preceeded
CLOS. CL's conditions could not be, since they were adopted into the
standard prior to the adoption of CLOS.)
I know that Barry knows this, too -- I'm not sure why several people
who know all about this are nitpicking some other knowledgable
statements, apparently to give the impression that this technology
did not exist before the late 1980s. The fact is, it has been in
Lisp, in almost exactly its current form, for over 25 years.
Condition handling is in Common Lisp because it was already a tried
and true technology when this dialect of the language was designed.
(That having been said, the version in Common Lisp was radically
innovative, by standards-commitee standards, in the sense that
it was a considerable chunk of language and was not a wholesale
verbatim adoption of the current practice. It was an actual
improvement and represents some notable innovation.
But it didn't just come out of the blue in 1986.)
I'm saying all this for newbies who might not know CL's history.
(I'm not sure what angle the other comments were coming from,
although I'm sure they're intended as positive information somehow.
I think the other guys know at least as much about this as I do.)
> > You must be using a nontraditional meaning for the word
> > "traditional".
>
> I think it's similar to the error handling mechanisms that are in CLU
> and Ada, both designed before Common Lisp. Most languages with
> error-handling mechanisms use termination semantics like HANDLER-CASE.
To amplify: the error handling in most languages today is the
simplistic kind of handling seen in some other older languages,
for example CLU or Ada. All those languages had the idea that
exceptions were conditions to be communicated seperately from the
normal flow, handlers, and they even had a signalling primitive.
CLU, for those who never heard of it, was a statically typed language
developed at MIT from 1973-1979. It was intended as a research
vehicle into programming methodology, heavily influenced by Simlua (67).
Its thrust was abstract data types and module-oriented programming.
The CLU exception handling model has the simplistic HANDLER-CASE
functionality (signalling code exits to the closest applicable
handler), and does not have resumption.
ADA also has dynamically-located exception handlers, and also lacks
resumption semantics. CLU has granularity of scope similar to Lisp;
handlers are attached to statements. I think in ADA the handlers
are attached to entire subroutines which are abandoned.
PL/I predates those, and had exception handling at least by 1972.
It did not have the extensible condition types -- just built-in ones,
but it had dynamically located handlers -- and it also had resumption
semantics like HANDLER-BIND. The designers of the modern "condition
system" exception handling feature in Lisp were Multics hackers,
and cite PL/I as their main inspiration.
Even BASIC, as I learned it around 1972, had the non-dynamic
non-extensible non-resumable exception handling concept:
500 ON EOF GOTO 6000
DONE
In article <·············@news.dtpq.com>,
······@news.dtpq.com (Christopher C. Stacy) wrote:
> Barry Margolin <······@alum.mit.edu> writes:
>
> > In article <··················@newssvr21.news.prodigy.com>,
> > "Steven M. Haflich" <···@alum.mit.edu> wrote:
> >
> > > Joe Marshall wrote:
> > >
> > > > HANDLER-CASE is a macro that is intended to work similarly to the
> > > > TRY/CATCH clauses in traditional languages.
> > >
> > > I _know_ you know this Joe, and I don't want to beat on your case,
> > > but newbies may get the wrong idea. HANDLER-CASE predates the
> > > similar constructs in "traditional" languages by 20 years or so.
> >
> > Hmm, Common Lisp is only about 20 years old now. So anything that it
> > predates by 20 years is something being developed as we speak.
>
> Common Lisp is a standardization of a Lisp, based almost entirely on
> the dialect that had these kinds of error handling in the early 1970s.
> To get more specific, the sophisticated object-oriented features date
> from the late 1970s. HANDLER-BIND et al. is a refinement of CONDITION-BIND.
> CONDITION-BIND was in Lisp by at least 1979. Common Lisp refined and
Hmm, the only error handling I remember in Lisp at that time was
Maclisp's ERRSET -- was CONDITION-BIND in another dialect at the time.
I thought the OO condition system was added a few years later in
Zetalisp. When did Kent write his condition-handling paper?
--
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
Barry Margolin <······@alum.mit.edu> writes:
> In article <·············@news.dtpq.com>,
> ······@news.dtpq.com (Christopher C. Stacy) wrote:
>
> > Barry Margolin <······@alum.mit.edu> writes:
> >
> > > In article <··················@newssvr21.news.prodigy.com>,
> > > "Steven M. Haflich" <···@alum.mit.edu> wrote:
> > >
> > > > Joe Marshall wrote:
> > > >
> > > > > HANDLER-CASE is a macro that is intended to work similarly to the
> > > > > TRY/CATCH clauses in traditional languages.
> > > >
> > > > I _know_ you know this Joe, and I don't want to beat on your case,
> > > > but newbies may get the wrong idea. HANDLER-CASE predates the
> > > > similar constructs in "traditional" languages by 20 years or so.
> > >
> > > Hmm, Common Lisp is only about 20 years old now. So anything that it
> > > predates by 20 years is something being developed as we speak.
> >
> > Common Lisp is a standardization of a Lisp, based almost entirely on
> > the dialect that had these kinds of error handling in the early 1970s.
> > To get more specific, the sophisticated object-oriented features date
> > from the late 1970s. HANDLER-BIND et al. is a refinement of CONDITION-BIND.
> > CONDITION-BIND was in Lisp by at least 1979. Common Lisp refined and
>
> Hmm, the only error handling I remember in Lisp at that time was
> Maclisp's ERRSET -- was CONDITION-BIND in another dialect at the time.
Actually, orthogonally to ERRSET [which was both a special form and a
variable that modified the behavior of the special form], Maclisp had
specific error handlers for about 8 or 10 specifically enumerated
conditions, each separately bindable. These included out of memory,
unbound variable, undefined function, etc.
But although I agree with most of Chris's statement of the history, I
believe he is wrong on the timing of CONDITION-BIND, which didn't
arrive until later. I think the condition system required Flavors. In
1979, I'm pretty sure the black lispm manual didn't define flavors. It
was still using names like TV-BEEP, not even a package system (or, at least,
not much of one) for namespace separation, and still using the PPC- (pieces
of paper) window system. TV:BEEP came later, as did the sheets window system.
And when the NES came long, I recall people saying "at least, a second use
for Flavors". (A lot of people liked Flavors in the window system examples
but couldn't figure out how to use it in anything other than windowing.)
> I thought the OO condition system was added a few years later in
> Zetalisp. When did Kent write his condition-handling paper?
1985 was my first error handling paper (an MIT working paper), I
think. It was an attempt to tell the larger community about what the
Symbolics language had recently done. It took years of lobbying, and
a freely available implementation, to get anyone to care. [Note well:
when I say "freely available" I mean something businesses could freely
incorporate in their products, not something with a GPL poison pill.
The GPL didn't exist then but I'm confident based upon my discussions
with people involved that a document that offered other than public domain
style priviliges would have failed to gain interest.]
See the first page of
http://www.nhplace.com/kent/CL/Revision-18.txt
for a brief statement of the history.
[Btw, you should say "in Symbolics Zetalisp", since although Symbolics
managed to successfully register the trademark Zetalisp, the LMITI
system used the name Zetalisp in a way that makes me not understand
how Symbolics managed to trademark it. The name is therefore not
nearly as useful as a unique name would have been since everyone had a
Zetalisp, and while for ordinary conversation among non-users they
were interchangeably exotic, for actual users, they each implied a
different set of features and the use of the unqualified term
(notwithstanding Symbolics' wishes to the contrary) just leads to
confusion.]
Barry Margolin <······@alum.mit.edu> writes:
> ······@news.dtpq.com (Christopher C. Stacy) wrote:
> > To get more specific, the sophisticated object-oriented features
> > date from the late 1970s. HANDLER-BIND et al. is a refinement of
> > CONDITION-BIND. CONDITION-BIND was in Lisp by at least 1979.
> > Common Lisp refined and
> Hmm, the only error handling I remember in Lisp at that time was
> Maclisp's ERRSET -- was CONDITION-BIND in another dialect at the time.
> I thought the OO condition system was added a few years later in
> Zetalisp.
Your question may be directed to Christopher Stacy, but unfortunately,
I don't think he will read your message.
> When did Kent write his condition-handling paper?
Kent's web site says "Exceptional Situations In Lisp" was written in
1985, with a new version appearing in 1990. The later version doesn't
seem to mention any other error handling mechanism in MacLisp than
ERRSET. I don't see much else in the ITS info MacLisp manual either.
Kent's other error handling paper, "Condition Handling in the Lisp
Language Family", mentions a New Error System written for Zetalisp in
the early 1980's. Supposedly there was an old error system, so I
guess the CONDITION-BIND Christopher Stacy writes about could have
been an earlier addition to Lisp Machine Lisp. (I'm just speculating
here.)
The 3rd edition of the Lisp Machine Manual from March 1981 documents
CONDITION-BIND, but I don't know if it's the new error system or the
old one.
······@news.dtpq.com (Christopher C. Stacy) writes:
> CLU, for those who never heard of it, was a statically typed language
> developed at MIT from 1973-1979. It was intended as a research
> vehicle into programming methodology, heavily influenced by Simlua (67).
> Its thrust was abstract data types and module-oriented programming.
> The CLU exception handling model has the simplistic HANDLER-CASE
> functionality (signalling code exits to the closest applicable
> handler), and does not have resumption.
Moreover, if I recall correctly, CLU used lexical, not dynamic, scoping
of handlers and the only dynamic handlers it had were for condition not
handled. (Someone who used CLU can correct me if this is a misunderstanding,
since I had someone explain this to me once but I never actually used the
language.)
I experimented with lexical scoping of handlers and found them personally to
always be the wrong thing. Perhaps sometime I'll try to explain why that is,
since I think I know. But not at this moment. For now I'll just end abruptly
by alleging without proof (here) that I think error handling is a necessarily
dynamic issue.
Note well that there is lexically interesting stuff that you CAN do to do
with the naming (and renaming) of conditions in a given lexical context.
Just as there are things you can do with an object system in like fashion.
But ignoring issues of names, there's the issue of substance behind the names,
and it is certainly not the case that the set of things you can meaningfully
handle can or should be lexically enumerated in exhaustive form.
Java attempts to straddle the middle with its uncomfortable mix of runtime
and static exceptions. I'm not sure that does much more than confuse people.
As some have noted, it mostly just provides an escape mechanism so that people
who don't like putting condition signatures in their function names can just
promote all errors to runtime errors, and hence avoid the issue.
Plus I've always thought it somewhat arbitrary that Java makes you put
conditions, but not I/O patterns in type signatures, and I've wondered if
the reason they don't do the latter is that users would rebel since the
decision to make people declare conditions is arguably a reason so many people
resort to writing text on the system console for debugging... to avoid the
overhead of declaration; imagine if they had to declare all those debugging
statements how many would say "enough is enough with these declarations!"
Kent M Pitman wrote:
> Java attempts to straddle the middle with its uncomfortable mix of runtime
> and static exceptions. I'm not sure that does much more than confuse people.
> As some have noted, it mostly just provides an escape mechanism so that people
> who don't like putting condition signatures in their function names can just
> promote all errors to runtime errors, and hence avoid the issue.
> Plus I've always thought it somewhat arbitrary that Java makes you put
> conditions, but not I/O patterns in type signatures, and I've wondered if
> the reason they don't do the latter is that users would rebel since the
> decision to make people declare conditions is arguably a reason so many people
> resort to writing text on the system console for debugging... to avoid the
> overhead of declaration; imagine if they had to declare all those debugging
> statements how many would say "enough is enough with these declarations!"
IIRC, the reason that the Java designers added statically checked
exceptions was as follows: Someone pushed for it, but they were
reluctant to do add that feature. However, they made an experiment and
added the static exceptions to the language. This revealed bugs in the
original implementation of the Java compiler, bugs which they apparently
didn't think of before, and that's what apparently convinced them.
(Unfortunately, I don't recall where I have read this. Maybe some
interview with James Gosling, but I don't know.)
This story also reveals why they couldn't see the problems that
statically checked exceptions impose: Static exceptions work relatively
well within fixed boundaries, i.e., within a standalone program or
within one component of a larger system. However, it doesn't work well
across componenents because the exceptions tell the client how they are
implemented internally. (Originally, Java only allowed for either
handling an exception or explicitly rethrowing it. This means that if
you see that some method throws, say, an RMIException, you
"accidentally" know that it somehow uses RMI internally.)
At some stage, Java added a feature to wrap a statically checked
exception with a dynamically checked one, but this creates other
problems. (You have to unwrap the exception in order to see what it was.)
Overall, in large programs statically checked exceptions create a number
of unnecessary problems, for example apart from the one mentioned above
also the fact that you cannot extend the list of thrown exceptions in a
subclass but only restrict it, which is counterintuitive, and that's for
example why Microsoft also dropped them for C#.
Pascal
--
OOPSLA'05 tutorial on generic functions & the CLOS Metaobject Protocol
++++ see http://p-cos.net/oopsla05-tutorial.html for more details ++++
Pascal Costanza wrote:
> This story also reveals why they couldn't see the problems that
> statically checked exceptions impose: Static exceptions work relatively
> well within fixed boundaries, i.e., within a standalone program or
> within one component of a larger system.
In a way explicit exceptions are akin to explicit arguments in pure
functional languages. If one functions needs to modify anything, the
whole chain needs to declare that variable/exception.
For variables the solution is dynamic extent, as provided by Lisp. A
good solution for static exceptions (which sound good to me in
principle) might be to allow a module to throw exceptions dynamically,
but have the package (or something like that on a larger scale) declare
them. Many exceptions will probably stay inside, just like some dynamic
variables stay inside packages in Lisp. (If one package interface says
that it throws a couple exceptions, the caller can again just skip
declaring them, unless they are exported over the caller's interface.)
> However, it doesn't work well
> across componenents because the exceptions tell the client how they are
> implemented internally. (Originally, Java only allowed for either
But a client using a component interface IMHO should know everything, so
that it can treat the interface as a black box. Documentation often
doesn't provide this, as most people don't care at all about good docs.
> handling an exception or explicitly rethrowing it. This means that if
> you see that some method throws, say, an RMIException, you
> "accidentally" know that it somehow uses RMI internally.)
Yes, and then it wouldn't hurt to make sure our stuff works if the
network goes down. If the RMIException isn't relevant, the module can
wrap it inside its own kind of FailureException.
> At some stage, Java added a feature to wrap a statically checked
> exception with a dynamically checked one, but this creates other
> problems. (You have to unwrap the exception in order to see what it was.)
Yes. Surely, for testing having dynamic exceptions works best, but
large-scale programming could use static ones if there were a few more
conveniences.
> Overall, in large programs statically checked exceptions create a number
> of unnecessary problems, for example apart from the one mentioned above
> also the fact that you cannot extend the list of thrown exceptions in a
> subclass but only restrict it, which is counterintuitive, and that's for
> example why Microsoft also dropped them for C#.
That's because the subclass doesn't honor the old interface. If you
want the subclass to fail in unexpected ways, the caller should be able
to deal with those failures (i.e. declare and use the subclass's
interface instead).
I just wanted to mention both sides. One big problem with Java (as
usual) is that its static stuff isn't just static, but very intrusive
and inconvenient the way it's designed.
--
State, the new religion from the friendly guys who brought you fascism.
Ulrich Hobelmann wrote:
> For variables the solution is dynamic extent, as provided by Lisp. A
> good solution for static exceptions (which sound good to me in
> principle) might be to allow a module to throw exceptions dynamically,
> but have the package (or something like that on a larger scale) declare
> them. Many exceptions will probably stay inside, just like some dynamic
> variables stay inside packages in Lisp. (If one package interface says
> that it throws a couple exceptions, the caller can again just skip
> declaring them, unless they are exported over the caller's interface.)
I don't know why this sounds good to you, but in practice it seems to be
exactly the other way around: The client of a component should not know
about details of its internal implementation, and statically checked
exception actually force you to leak such internals (or provide some
nasty workarounds to hide them). Say, in one version of the component it
uses CORBA to talk to a different server and in another it uses SOAP.
Why should a client component worry about CORBA vs. SOAP specific
exceptions, especially when such exception can only be dealt with at the
highest level of a program anyway?
It's only that within the boundaries of a component that statically
checked exceptions have some limited usefulness because they potentially
make you check all execution paths. Although I have seen try { ... }
catch (Exception e) { /*todo*/ } quite a lot which is _much_ worse than
what dynamically checked exceptions do by default. (Since in Java the
exception hierarchy is screwed up, this even catches RuntimeExceptions!)
> Yes, and then it wouldn't hurt to make sure our stuff works if the
> network goes down. If the RMIException isn't relevant, the module can
> wrap it inside its own kind of FailureException.
This is exactly the typical answer from static typers: Adapt your coding
style to the requirements of the programming language, not the other way
around. Yuck.
> Yes. Surely, for testing having dynamic exceptions works best, but
> large-scale programming could use static ones if there were a few more
> conveniences.
Well, as I said, Microsoft claims to have done an evaluation of large
programs, and they concluded that static exceptions incurs more costs
than benefits _especially_ in such large programs. That's why they
dropped them for C#. I don't think they published the exact details so
it cannot be verified, but according to my own experiences their claim
makes a lot of sense to me.
Pascal
--
OOPSLA'05 tutorial on generic functions & the CLOS Metaobject Protocol
++++ see http://p-cos.net/oopsla05-tutorial.html for more details ++++
Kent M Pitman <······@nhplace.com> writes:
> Moreover, if I recall correctly, CLU used lexical, not dynamic, scoping
> of handlers and the only dynamic handlers it had were for condition not
> handled. (Someone who used CLU can correct me if this is a misunderstanding,
> since I had someone explain this to me once but I never actually used the
> language.)
No, I'm pretty sure the language had dynamically scoped exception
handlers. I do believe they required that the set of errors be
explicitly listed on any method that throws them (like Java does).
> I experimented with lexical scoping of handlers and found them personally to
> always be the wrong thing. Perhaps sometime I'll try to explain why that is,
> since I think I know. But not at this moment. For now I'll just end abruptly
> by alleging without proof (here) that I think error handling is a necessarily
> dynamic issue.
I can't imagine lexical error handling working in any reasonable way.
Joe Marshall <·········@alum.mit.edu> writes:
> Kent M Pitman <······@nhplace.com> writes:
>
> > Moreover, if I recall correctly, CLU used lexical, not dynamic,
> > scoping of handlers and the only dynamic handlers it had were for
> > condition not handled. (Someone who used CLU can correct me if
> > this is a misunderstanding, since I had someone explain this to me
> > once but I never actually used the language.)
>
> No, I'm pretty sure the language had dynamically scoped exception
> handlers. I do believe they required that the set of errors be
> explicitly listed on any method that throws them (like Java does).
Ah, it's coming back to me slightly... let me try again, and tell me if
this seems right: was it required that you either handle them in the
immediate caller by its proper name or else other callers farther out
would see it as just unhandled? (That would probably be superior to
Java's desire to have the entire call chain know.)
Kent M Pitman <······@nhplace.com> writes:
> Joe Marshall <·········@alum.mit.edu> writes:
>
>> Kent M Pitman <······@nhplace.com> writes:
>>
>> > Moreover, if I recall correctly, CLU used lexical, not dynamic,
>> > scoping of handlers and the only dynamic handlers it had were for
>> > condition not handled. (Someone who used CLU can correct me if
>> > this is a misunderstanding, since I had someone explain this to me
>> > once but I never actually used the language.)
>>
>> No, I'm pretty sure the language had dynamically scoped exception
>> handlers. I do believe they required that the set of errors be
>> explicitly listed on any method that throws them (like Java does).
>
> Ah, it's coming back to me slightly... let me try again, and tell me if
> this seems right: was it required that you either handle them in the
> immediate caller by its proper name or else other callers farther out
> would see it as just unhandled? (That would probably be superior to
> Java's desire to have the entire call chain know.)
I think you might be right about this. I think you needed to
explicitly state that you wanted to rethrow the exception.
WoodHacker wrote:
> Can someone explain to me have to pass a parameter to the error system?
> I'm loading a font and if the font is invalid or not found, I want to
> report an error. (I have this working with handler-bind). However,
> I would like to show the user what he/she was using for a font name.
> I can't seem to find any way to pass the name of the font on to the
> handler function. I know this must be possible...
The _only_ thing the handler function receives is the condition
object that was signalled by error. The proper way to do what
you want is to define an appropriate new condition type with
slots for the data you want to pass to the handler, and readers
for those slots. There are examples of defining new conditions
on the DEFINE-CONDITION page of the ANS. See 9.1.2.1 Condition
Designators to figure out how to instantiate a condition.