From: Rainer Joswig
Subject: question on reporting a CONDITION in ANSI CL
Date: 
Message-ID: <joswig-5E8412.12140203112000@news.is-europe.net>
Hi,

is it necessary to define the report function inside
a DEFINE-CONDITION form?

(define-condition machine-not-available-error (machine-error) ()
  (:report (lambda (condition stream)
             (format stream "The machine ~A is not available."
                     (machine-error-machine-name condition)))))

Or should it also be possible to write:

(define-condition machine-not-available-error (machine-error) ())

(defmethod print-object ((condition machine-not-available-error) stream)
  (if *print-escape*
    (call-next-method)
    (format stream "The machine ~A is not available."
                     (machine-error-machine-name condition))))

If yes, then the Lisp system usually would need to bind
*PRINT-ESCAPE* to NIL before reporting the error.
Is that true?

Rainer Joswig

-- 
Rainer Joswig, Hamburg, Germany
Email: ·············@corporate-world.lisp.de
Web: http://corporate-world.lisp.de/

From: Kent M Pitman
Subject: Re: question on reporting a CONDITION in ANSI CL
Date: 
Message-ID: <sfwd7gd5m0b.fsf@world.std.com>
Rainer Joswig <······@corporate-world.lisp.de> writes:

> is it necessary to define the report function inside
> a DEFINE-CONDITION form?

Historically, the condition system and CLOS were introduced in parallel, with
an attempt not to make one depend on the other.  There were strongly stated
desires (whether or not they resulted in material effects in any 
implementation, I don't know) to create CLOS-free delivery of systems that
made use of the condition system.  Use of :report in DEFINE-CONDITION
offers a system the possibility of delivering your code sans CLOS support,
in a potentially smaller application.

My personal recommendation is that if this is the only DEFMETHOD your system
will do, you should not do it.  But if you are doing defmethod elsewhere,
you probably shouldn't care which style you use.

> ... should it also be possible to write:
> 
> (define-condition machine-not-available-error (machine-error) ())
> 
> (defmethod print-object ((condition machine-not-available-error) stream)
>   (if *print-escape*
>     (call-next-method)
>     (format stream "The machine ~A is not available."
>                      (machine-error-machine-name condition))))
> 
> If yes, then the Lisp system usually would need to bind
> *PRINT-ESCAPE* to NIL before reporting the error.
> Is that true?

Yes.  You should always "print" a condition with *print-escape* false
if you want the person to see the message; that is, you should PRINC it.
From: Pierre R. Mai
Subject: Re: question on reporting a CONDITION in ANSI CL
Date: 
Message-ID: <87aebh53k7.fsf@orion.bln.pmsf.de>
Kent M Pitman <······@world.std.com> writes:

> Historically, the condition system and CLOS were introduced in parallel, with
> an attempt not to make one depend on the other.  There were strongly stated
> desires (whether or not they resulted in material effects in any 
> implementation, I don't know) to create CLOS-free delivery of systems that
> made use of the condition system.  Use of :report in DEFINE-CONDITION
> offers a system the possibility of delivering your code sans CLOS support,
> in a potentially smaller application.

Indeed CMU CL can be set up to provide a system without CLOS (and
without a compiler, too), but still providing the full condition
system (which is still non-CLOS based in CMU CL).

But given that a full CMU CL core nowadays is only ~ 20MB, and given
the increasing use of CLOS in most serious CL applications, this is
of little practical interest nowadays.  Indeed the desire for a
tighter integration of PCL/CLOS into CMU CL will probably put an end
to this option at some point in the future...

Regs, Pierre.

-- 
Pierre R. Mai <····@acm.org>                    http://www.pmsf.de/pmai/
 The most likely way for the world to be destroyed, most experts agree,
 is by accident. That's where we come in; we're computer professionals.
 We cause accidents.                           -- Nathaniel Borenstein
From: Rainer Joswig
Subject: Re: question on reporting a CONDITION in ANSI CL
Date: 
Message-ID: <joswig-A61F92.12544003112000@news.is-europe.net>
In article <···············@world.std.com>, Kent M Pitman 
<······@world.std.com> wrote:

> Rainer Joswig <······@corporate-world.lisp.de> writes:
> 
> > is it necessary to define the report function inside
> > a DEFINE-CONDITION form?
> 
> Historically, the condition system and CLOS were introduced in parallel, with
> an attempt not to make one depend on the other.  There were strongly stated
> desires (whether or not they resulted in material effects in any 
> implementation, I don't know) to create CLOS-free delivery of systems that
> made use of the condition system.  Use of :report in DEFINE-CONDITION
> offers a system the possibility of delivering your code sans CLOS support,
> in a potentially smaller application.
> 
> My personal recommendation is that if this is the only DEFMETHOD your system
> will do, you should not do it.  But if you are doing defmethod elsewhere,
> you probably shouldn't care which style you use.
> 
> > ... should it also be possible to write:
> > 
> > (define-condition machine-not-available-error (machine-error) ())
> > 
> > (defmethod print-object ((condition machine-not-available-error) stream)
> >   (if *print-escape*
> >     (call-next-method)
> >     (format stream "The machine ~A is not available."
> >                      (machine-error-machine-name condition))))
> > 
> > If yes, then the Lisp system usually would need to bind
> > *PRINT-ESCAPE* to NIL before reporting the error.
> > Is that true?
> 
> Yes.  You should always "print" a condition with *print-escape* false
> if you want the person to see the message; that is, you should PRINC it.

I think MCL does it wrong. I wonder if other Lisp systems are
doing this right.

-- 
Rainer Joswig, Hamburg, Germany
Email: ·············@corporate-world.lisp.de
Web: http://corporate-world.lisp.de/
From: Kent M Pitman
Subject: Re: question on reporting a CONDITION in ANSI CL
Date: 
Message-ID: <sfwd7gd2pa9.fsf@world.std.com>
Rainer Joswig <······@corporate-world.lisp.de> writes:

> 
> In article <···············@world.std.com>, Kent M Pitman 
> <······@world.std.com> wrote:
> 
> > Rainer Joswig <······@corporate-world.lisp.de> writes:
> >
> > > If yes, then the Lisp system usually would need to bind
> > > *PRINT-ESCAPE* to NIL before reporting the error.
> > > Is that true?
> > 
> > Yes.  You should always "print" a condition with *print-escape* false
> > if you want the person to see the message; that is, you should PRINC it.
> 
> I think MCL does it wrong. I wonder if other Lisp systems are
> doing this right.

From CLHS 9.1.3 (Printing Conditions):

 "... When a condition is printed and *print-escape* is false,
     the condition reporter for the condition is invoked.  ..."

Now, just to be TOTALLY clear about this, the wording of the spec does
not say that *PRINT-ESCAPE* has to be NIL to call the condition
reporter, what it says is that the condition reporter will be called
if *PRINT-ESCAPE* is false.  I think that means that use of PRINC and
FORMAT's ~A will cause the reporter to be called, but I think it doesn't
imply that just because the reporter is called, *PRINT-ESCAPE* is false.
It's possible that the reporter defines a SYSTEM:REPORT-CONDITION or
some such which can be called from other places as well when *PRINT-ESCAPE*
is true.  I mention this not because I think it matters really a lot in
practice, but your wording in your original question is not quite right:
you don't have to bind *PRINT-ESCAPE* before reporting the error, you just
have to bind it before reporting it by calling a function (specifically
WRITE or one of its friends) the principal job of which is not to report the 
error, but which can be cajoled into calling the reporter by this special
cue.  Or, at least, that's my personal take.  Just to allow MCL at least
a bit of wiggle room...
From: ······@corporate-world.lisp.de
Subject: Re: question on reporting a CONDITION in ANSI CL
Date: 
Message-ID: <8tvioh$854$1@nnrp1.deja.com>
In article <···············@world.std.com>,
  Kent M Pitman <······@world.std.com> wrote:
> Rainer Joswig <······@corporate-world.lisp.de> writes:
>
> >
> > In article <···············@world.std.com>, Kent M Pitman
> > <······@world.std.com> wrote:
> >
> > > Rainer Joswig <······@corporate-world.lisp.de> writes:
> > >
> > > > If yes, then the Lisp system usually would need to bind
> > > > *PRINT-ESCAPE* to NIL before reporting the error.
> > > > Is that true?
> > >
> > > Yes.  You should always "print" a condition with *print-escape* false
> > > if you want the person to see the message; that is, you should PRINC it.
> >
> > I think MCL does it wrong. I wonder if other Lisp systems are
> > doing this right.
>
> From CLHS 9.1.3 (Printing Conditions):
>
>  "... When a condition is printed and *print-escape* is false,
>      the condition reporter for the condition is invoked.  ..."
>
> Now, just to be TOTALLY clear about this, the wording of the spec does
> not say that *PRINT-ESCAPE* has to be NIL to call the condition
> reporter, what it says is that the condition reporter will be called
> if *PRINT-ESCAPE* is false.  I think that means that use of PRINC and
> FORMAT's ~A will cause the reporter to be called, but I think it doesn't
> imply that just because the reporter is called, *PRINT-ESCAPE* is false.
> It's possible that the reporter defines a SYSTEM:REPORT-CONDITION or
> some such which can be called from other places as well when *PRINT-ESCAPE*
> is true.  I mention this not because I think it matters really a lot in
> practice, but your wording in your original question is not quite right:
> you don't have to bind *PRINT-ESCAPE* before reporting the error, you just
> have to bind it before reporting it by calling a function (specifically
> WRITE or one of its friends) the principal job of which is not to report the
> error, but which can be cajoled into calling the reporter by this special
> cue.  Or, at least, that's my personal take.  Just to allow MCL at least
> a bit of wiggle room...

My question is more in this direction:

- Let's assume the Lisp system does error reporting in various places.
- how do I write Condition classes with special reporting
  functionality (say, with looking up the error string from
  a table)? Portably?
- I especially don't want to specify the report method in the
  DEFINE-CONDITION form. Something like a PRINT-OBJECT method
  would be fine, so that I can use CLOS mechanisms.
- What do I need to do, that the Lisp system will call my
  reporting code and what does my reporting code have to
  expect (say as the value of *PRINT-ESCAPE*)?

I'm not really sure, that I like the PRINT-OBJECT idea.
A REPORT-CONDITION generic function would be nice.

MCL for example calls some condition reporter function (when
invoking the error break loop), which then binds *PRINT-ESCAPE* to
T and then calls PRINT-OBJECT on the condition object.

What do you think?

Rainer Joswig




Sent via Deja.com http://www.deja.com/
Before you buy.
From: Kent M Pitman
Subject: Re: question on reporting a CONDITION in ANSI CL
Date: 
Message-ID: <sfw3dh8a1e1.fsf@world.std.com>
······@corporate-world.lisp.de writes:

> My question is more in this direction:
> 
> - Let's assume the Lisp system does error reporting in various places.
> - how do I write Condition classes with special reporting
>   functionality (say, with looking up the error string from
>   a table)? Portably?
> - I especially don't want to specify the report method in the
>   DEFINE-CONDITION form. Something like a PRINT-OBJECT method
>   would be fine, so that I can use CLOS mechanisms.
> - What do I need to do, that the Lisp system will call my
>   reporting code and what does my reporting code have to
>   expect (say as the value of *PRINT-ESCAPE*)?
> 
> I'm not really sure, that I like the PRINT-OBJECT idea.

Hmm.  I looked more at this and decided there's probably no way you can
conform to the spec and not go through the PRINT-OBJECT.  Just my opinion,
though--some implementations may differ.  I do think the intended thing is

> A REPORT-CONDITION generic function would be nice.

I agree.  It was downright stupid not to have put it in.  Btw, I think as
a rule it's a mistake not to have a default PRINT-OBJECT that does

(defmethod print-object ((x ..various broad classes..) stream)
  (if *print-escape*
      (prin1-object x stream)
      (princ-object x stream)))

with a default PRINC-OBJECT that just calls PRIN1-OBJECT.  There should 
probably also be a mixin that replaces prin1-object with

  (defmethod print-object ((x prin1->princ-mixin) stream)
    (print-unreadable-object (x stream :type t :identity t)
      (princ-object x stream)))

because I get tired of writing these methods over and over and over in all
my code.  But so it goes.

> MCL for example calls some condition reporter function (when
> invoking the error break loop), which then binds *PRINT-ESCAPE* to
> T and then calls PRINT-OBJECT on the condition object.

Well, maybe they are intending to show the object itself.  If they're intending
the report data for the object to show up when they do that, my feeling is
that they're probably confused.