Subject: [clisp-list] Re: Apparent #S reader problem in 2.32

From: Bruno Haible <[email-masked]>
Date: Thu Jan 8 08:05:01 2004

Sam wrote:
> this is caused by make-init-form in loadform.lisp: no-*-method signal
> either TYPE-ERROR or just ERROR and both have to be ignored in
> make-init-form.
> we have the following options:
>
>  - ignore _all_ errors there (what about, say, compilation errors?!)

Generally a bad idea.

>  - add
>
> ;; for no-applicable-method, no-primary-method, no-next-method
> (define-condition method-error (simple-error)
>   (($gf :initarg :generic-function :reader method-error-generic-function)
>    ($args :initarg :argument-list :reader method-error-argument-list)))
> (define-condition method-type-error (method-error simple-type-error) ())
>
>    to condition.lisp with appropriate modifications to clos.lisp and
>    exporting METHOD-*ERROR* from CLOS and EXT.

Yes, that's the way to go. Introducing more specific condition types never
hurts.

I would call these 'method-call-error' and 'method-call-type-error', since
it's a problem not with the method but with its arguments.

>  - modification of the above removing METHOD-TYPE-ERROR and the whole
>    "dispatching arg" thing from clos.lisp - I don't see how it is useful.

This is nonsense. NO-APPLICABLE-METHOD goes to great lengths to provide
a TYPE-ERROR if possible. This is a feature for the user who want to
catch errors. If you have code that relies on the fact that a condition's
type is _exactly_ ERROR and not a subtype of ERROR, this code is wrong:
the code which signals the condition is always free to create a more
specific condition type.

Bruno

---

From: Sam Steingold <[email-masked]>
Date: Thu Jan 8 08:23:14 2004

> * Bruno Haible <[email-masked]> [2004-01-08 17:01:39 +0100]:
>
> Sam wrote:
>
> This is nonsense. NO-APPLICABLE-METHOD goes to great lengths to
> provide a TYPE-ERROR if possible. This is a feature for the user who
> want to catch errors. If you have code that relies on the fact that a
> condition's type is _exactly_ ERROR and not a subtype of ERROR, this
> code is wrong: the code which signals the condition is always free to
> create a more specific condition type.

Yes, I understand what you are doing there.
I just doubt that anyone is using this feature.
If you want to keep it - it is fine with me.
I will check in the patch soon.

-- 
Sam Steingold (http://www.podval.org/~sds) running w2k
<http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/>
<http://www.mideasttruth.com/> <http://www.honestreporting.com>
A PC without Windows is like ice cream without ketchup.

---

From: Bruno Haible <[email-masked]>
Date: Thu Jan 8 08:55:00 2004

> I just doubt that anyone is using this feature.

Even if there is no documentation about the precise condition type signalled
in a particular situation, people often display the error condition, to see
what type it belongs to, and then use HANDLER-BIND with this condition type.

So, signalling ERROR instead of TYPE-ERROR creates a backwards compatibility
problem. But signalling XYZ-ERROR instead of ERROR doesn't create a backward
compatibility problem, if the handling code is written in a sane way.

Bruno

---

From: Kaz Kylheku <[email-masked]>
Date: Thu Jan 8 09:10:03 2004

> > either TYPE-ERROR or just ERROR and both have to be ignored in

More detail: the problem that occurs in my particular test case goes like
this: CLISP wants to print a struct object via PRINT-OBJECT. Because this
is at compile time, and the object came from the #S syntax, there is a
cached form which depends on MAKE-LOAD-FORM being specialized for that
struct. So the pretty printer tries to use the load form, and blows up
on the lack of a method.

Now the problem is that the error which is generated is caught in a
HANDLER-CASE in MAKE-INIT-FORM which wants to print the offending object
rather than ignore the error! So an infinite recursion is caused
through PRINT-OBJECT back to MAKE-INIT-FORM, because it's the printing
of the object that causes the error.

The real problem is that both MAKE-INIT-FORM tries to take the error
handling into its own hands, so to speak, rather than defer it to the
calling layers.  MAKE-INIT-FORM has a brain-damaged HANDLER-CASE
which tries to guess which errors might be method problems. It's wrong
to catch errors at this level, because not only does it lead to the
looping behavior, but it makes it impossible for the highest level to
provide a specific, accurate diagnostic relevant to the real problem.

PRINT-OBJECT falls back on PRINT-UNREADABLE-OBJECT if MAKE-INIT-FORM
returns NIL. But this is a problem if MAKE-INIT-FORM returns NIL
because it silently caught an error! What if the unreadable object is
unacceptable to the caller of PRINT-OBJECT? If you are using PRINT-OBJECT
to dump to a .FAS file, for instance, and you get some unreadable
representation, you end up with a garbage .FAS that won't load.

A NIL return from MAKE-INIT-FORM should really mean ``There is no init
form available, and this is okay'' not ``There is no init form available,
possibly because of a nasty error that was swept under the rug''.

Ultimately, it would really be good to raise a specific error which tells
the programmer: ``You used #s() to specify a struct literal in
compiled code, but did not specialize a MAKE-LOAD-FORM method for that
struct type!  See ANSI CL 3.2.4.4'' :)

---

From: Bruno Haible <[email-masked]>
Date: Sun Jan 18 10:22:01 2004

> provide a specific, accurate diagnostic relevant to the real problem.

You are entirely right. I've fixed this now in the CVS, by introducing
a condition class which describes _exactly_, not just vaguely, the situation
that MAKE-INIT-FORM wants to handle.

> struct type!  See ANSI CL 3.2.4.4'' :)

Thanks for the suggestion. I've added similar text to the error message.

Bruno