[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Issue: CLOS-CONDITIONS (Version 3)



I believe I agreed that the cleanup committee would take over this issue. It was discussed in the Error Committee report at a previous meeting in 1988, but not voted on at the time.

As you can see, there are comments...
     ----- Begin Forwarded Messages -----

Return-Path: <X3J13-mailer@SAIL.Stanford.EDU>
Received: from SAIL.Stanford.EDU ([36.86.0.194]) by Xerox.COM ; 09 OCT 88 02:50:46 PDT
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by SAIL.Stanford.EDU with TCP; 9 Oct 88  02:30:05 PDT
Received: from BOBOLINK.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 473546; Sun 9-Oct-88 05:28:47 EDT
Date: Sun, 9 Oct 88 05:28 EDT
 From: CL-ERROR-HANDLING@SAIL.Stanford.EDU
Sender: KMP@STONY-BROOK.SCRC.Symbolics.COM
Subject: Draft Issue: CLOS-CONDITIONS (Version 3)
To: X3J13@SAIL.Stanford.EDU
Message-ID: <881009052832.8.KMP@BOBOLINK.SCRC.Symbolics.COM>

There's been some disagreement about a couple of details, so this may
change yet again before we ask you to vote on it, but this is the
version that is likely to be presented for comment at the meeting.
The conflict is represented in the writeup by the presence of two
variant proposals, YES-OPTION-A and YES-OPTION-B.

-----
Issue:        CLOS-CONDITIONS
References:   Condition System (Revision 18)
Category:     ADDITION
Edit history: 26-Sep-88, Version 1 by Pitman
	      06-Oct-88, Version 2 by Pitman
	      09-Oct-88, Version 3 by Pitman
Status:	      For Internal Discussion

Problem Description:

  The description of the Common Lisp condition system presupposes
  only DEFSTRUCT and not DEFCLASS because it was written when
  CLOS had not been adopted. It is stylistically out of step with
  CLOS in a few places and places some restrictions which are not
  necessary if CLOS can be presupposed.

Subproposal (CLOS-CONDITIONS:YES):

  [These options are very similar. They agree except as otherwise noted.]

  Define that condition types are CLOS classes.

  Define that condition objects are CLOS instances.

  Permit multiple parent-types to be named in the list of
  parent types. Define that these parent types are treated the
  same as the superior class list in a CLOS DEFCLASS expression.

  Define that slots in condition objects are normal CLOS slots.
  Note that WITH-SLOTS can be used to provide more convenient
  access to the slots where slot accessors are undesirable.

  Functions such as SIGNAL, which take arguments of class names,
  are permitted to take class objects. Such class objects must
  still be subclasses of CONDITION.

  Eliminate the :CONC-NAME option to DEFINE-CONDITION.

  Define that condition reporting is mediated through the
  PRINT-OBJECT method for the condition type (class) in question,
  with *PRINT-ESCAPE* always being NIL. Specifying 
  (:REPORT fn) in the definition of a condition type C is
  equivalent to doing
   (DEFMETHOD PRINT-OBJECT ((X c) STREAM)
     (IF *PRINT-ESCAPE* (CALL-NEXT-METHOD) (fn X STREAM)))

Proposal (CLOS-CONDITIONS:YES-OPTION-A):

  All of subproposal YES, plus the following...

  Extend the syntax for a slot in a DEFINE-CONDITION as follows...
   - If a symbol is used, DEFINE-CONDITION will by special case
     treat this as if (symbol :INITARG keyword :READER reader-name)
     were specified instead, where KEYWORD is generated by
	(INTERN (SYMBOL-NAME symbol) (FIND-PACKAGE "KEYWORD"))
     and reader-name is generated by
	(INTERN (FORMAT NIL "~A-~A" condition-type symbol))
     for CONDITION-TYPE being the condition type being defined.

   - A length 1 list, (symbol), is treated the same as providing
     the symbol itself.

   - If a length 2 list, (symbol value) is provided, it is treated
     as (symbol :INITARG keyword :READER reader-name :INITFORM value),
     with KEYWORD and READER-NAME being computed as above.

   - If a list of length greater than 2 is used, it is treated
     the same as a CLOS slot-specifier. In that case, the :INITARG
     and :READER options must be explicitly specified if desired.

  This syntax is compatible with the existing semantics of
  DEFINE-CONDITION.

  Rationale:

    This provides maximal compatibilty with the old semantics
    for DEFINE-CONDITION, which numerous vendors now distribute.

    Further, and perhaps more importantly, the uses of slots in
    DEFINE-CONDITION are highly constrained. They are not assigned
    so an INITARG is nearly always needed. There are almost
    universally accessed externally, so a :READER is usually
    needed. This syntax makes what is by far the most convenient
    use very syntactically simple.

Proposal (CLOS-CONDITIONS:YES-OPTION-B):

  Incompatibly change the syntax of a slot in DEFINE-CONDITION
  to be compatible with a DEFCLASS slot specification.

  An implication of this change is that forms like
   (DEFINE-CONDITION FOO (BAR) ((A 1) (B 2)))
  would have to be written
   (DEFINE-CONDITION FOO (BAR) ((A :INITARG :A :READER FOO-A :INITFORM 1)
			        (B :INITARG :B :READER FOO-B :INITFORM 2)))

  Rationale: This is most compatible with CLOS.

Examples:

  Slot specifiers...

    Under YES-OPTION-A ...

       A slot specifier of X in condition type FOO is still valid
       and means the same as (X :INITARG :X :READER FOO-X).
     
       A slot specifier of (X) in condition type FOO is still valid
       and means the same as (X :INITARG :X :READER FOO-X).
     
       A slot specifier of (X V) in condition type FOO is still
       valid and means the same as 
	(X :INITARG :X :READER FOO-X :INITFORM V).
       
       In addition, other slot specifiers such as
	(X :INITARG :EX :TYPE FIXNUM)
       are permitted as in DEFCLASS.
   
    Under YES-OPTION-B ...

       A slot specifier of X is still valid but is incompatibly
       changed to mean what CLOS has it mean; no :INITARG or 
       :READER would be supplied.
     
       A slot specifier of (X) is still valid but is incompatibly
       changed to mean what CLOS has it mean; no :INITARG or 
       :READER would be supplied.

       A slot specifier of (X V) would no longer be valid.
       
       In addition, other slot specifiers such as
	(X :INITARG :EX :TYPE FIXNUM)
       are permitted as in DEFCLASS.

 Conc names ...

   (DEFINE-CONDITION FOOBAR (FOO BAR) (X Y) (:CONC-NAME FUBAR))
   would be rewritten
   (DEFINE-CONDITION FOOBAR (FOO BAR)
     ((X :INITARG :X :READER FUBAR-X)
      (Y :INITARG :Y :READER FUBAR-Y)))

 Report methods ...

   (DEFINE-CONDITION OOPS (ERROR) ())
   (DEFMETHOD PRINT-OBJECT ((X OOPS) STREAM)
     (IF *PRINT-ESCAPE* 
	 (CALL-NEXT-METHOD)
	 (FORMAT STREAM "Oops! Something went wrong.")))
   (ERROR 'OOPS)
   >>Error: Oops! Something went wrong.

Rationale:

  These changes are consistent with the intent of the recent
  X3J13 endorsement of CLOS and the Common Lisp Condition System.

  The shorthand notations for DEFINE-CONDITION's slots spec
  are justified since the the way in which condition slots are
  used is much more highly constrained than for arbitrary classes.
  This means we can predict what will be the common case and make
  it far more syntactically convenient than it might otherwise be.

  Although flushing :CONC-NAME is an incompatible change, nothing
  forbids an implementation from supporting it as an extension
  during a transition period.

Current Practice:

  Some implementations supporting CLOS probably already do this,
  or something very similar.

Cost to Implementors:

  If you really have CLOS, this is very straightforward.

Cost to Users:

  Small, but tractable.

  The main potential problems are:

   - :CONC-NAME. There is nothing that keeps an implementation from
     continuing to support :CONC-NAME for a short while until old code
     has been upgraded.

   - The incompatible change to slot syntax. Again, it is possible to
     unambiguously recognize a 2-list as old-style syntax and an
     implementation can provide interim compatibility support during
     a transition period.

  Even if implementations did not provide the recommended compatibility
  support, users could trivially shadow DEFINE-CONDITION and provide the
  support themselves, expanding into the native DEFINE-CONDITION in the
  proper syntax.

Cost of Non-Adoption:

  Conditions will seem harder to manipulate than other user-defined types.

  People will wonder if CLOS is really something we're committed to.

Benefits:

  A more regular language.

Aesthetics:

  Anything that makes the language more regular improves the aesthetics.

Discussion:

  People seem to disagree about the status that CLOS might occupy
  in the upcoming standard. In spite of a vote of support, they seem
  to think it might be optional in some way. Passing this proposal
  establishes a clear precedent for the full integration of CLOS into
  the emerging language.

  Moon suggests that we might want to add condition types for the errors
  CLOS might signal. It isn't obvious (to Pitman, at least) that this 
  change is as straightforward as it looks, though, so it will have to
  come up under separate cover.

  Richard Mlynarik suggests adding a generic function, REPORT-CONDITION,
  which is used for reporting conditions. It is possible to discuss such
  a generic function as a separate issue layered atop the substrate which
  this proposal provides, so that issue has been deferred.

  Pitman supports this change, with mild preference for YES-OPTION-A.
  Gregor supports this change, with strong preference for YES-OPTION-B.



     ----- Next Message -----

Return-Path: <Mly%AI.AI.MIT.EDU@XX.LCS.MIT.EDU>
Received: from XX.LCS.MIT.EDU ([10.0.0.44]) by Xerox.COM ; 30 OCT 88 11:34:02 PST
Received: from NICKB.AI.MIT.EDU by XX.LCS.MIT.EDU via Chaosnet; 30 Oct 88 14:32-EST
Date: Sun, 30 Oct 88 14:34 EST
 From: Richard Mlynarik <Mly@AI.AI.MIT.EDU>
Subject: Re: Draft Issue: CLOS-CONDITIONS (Version 3)
To: masinter.pa
cc: gregor.pa
In-Reply-To: <881026-153859-14085@Xerox>
Included-msgs: <19881007052142.8.MLY@JACKIE.AI.MIT.EDU>
Message-ID: <19881030193406.7.MLY@NICKB.AI.MIT.EDU>
Character-Type-Mappings: (1 0 (NIL 0) (NIL :ITALIC NIL) "CPTFONTI")
Fonts: CPTFONT, CPTFONTI

    Date: 26 Oct 88 15:38 PDT
    From: masinter.pa@Xerox.COM

    I thought there might be a way to word this proposal in a way that would
    make the error/signal system *compatible* with CLOS but not to actually
    make it require the low-level implementation to *use* CLOS if it didn't
    want to. Many vendors are only now working on integrating CLOS into their
    environment. A lot of the concern is for "staging" the introduction of CLOS
    and the condition system. This is also a concern for those with existing
    implementations where they might want to load in the CLOS support late in
    the system-building process, and yet use the condition system early in that
    process. While this is an implementation detail, the implementation
    ramifications of your proposal need to be spelled out.

    [...]

I sent the following comments to Pitman.
I guess I don't really care that much about this anymore, since I think
that the error Standard is pretty broken.  The phrase ``swimming up
waterfalls'' comes to mind.

Date: Fri, 7 Oct 88 01:21 EDT
 From: Richard Mlynarik <MLY@AI.AI.MIT.EDU>
Subject: Issue: CLOS-CONDITIONS (Version 2)
To: KMP@STONY-BROOK.SCRC.SYMBOLICS.COM
cc: Moon@STONY-BROOK.SCRC.SYMBOLICS.COM
In-Reply-To: <881006162757.4.KMP@BOBOLINK.SCRC.Symbolics.COM>
Message-ID: <19881007052142.8.MLY@JACKIE.AI.MIT.EDU>

[Mailing list removed]

I had promised myself that I would have no more to do with this
Error Standard but nevertheless...

    Date: Thu, 6 Oct 88 16:27 EDT
    From: Kent M Pitman <KMP@STONY-BROOK.SCRC.Symbolics.COM>

      The description of the Common Lisp condition system presupposes
      only DEFSTRUCT and not DEFCLASS because it was written when
      CLOS had not been adopted. It is stylistically out of step with
      CLOS in a few places and places some restrictions which are not
      necessary if CLOS can be presupposed.

    Proposal (CLOS-CONDITIONS:YES):

      Define that condition types are CLOS classes.

      Define that condition objects are CLOS instances.

This is certainly desirable.  However, it ignores a pragmatic problem:

* Even though CLOS has been adopted, it is not widely supported.
  (Support means `supplied by vendors' rather than `you can use PCL')
* The error system is much simpler to implement than CLOS.
  The error system is perceived to be more critical than CLOS.
  (For example, I believe that Lucid supply an implementation of
  something like KMP's error system in their 3.0 Lisp release.  They do
  not supply any CLOS or CLOS-precursor support as far as I know.)

Therefore...

It would be nice if the standard were worded in such a way that it
allowed a non-CLOS implementation.  Given that the only
`object-oriented' features that the error standard requires are

* TYPEP
* slot inheritance
* report-function inheritance (with no method-combination)

and since it is very easy to write a toy class system which implements
just those features, let me suggest that the DEFINE-CONDITION macro not
implicitly define :READERs.  Readers presuppose CLOS generic functions a
little too much.  I feel that a better (interim -- all discussion here
is interim) solution would be to define the function SLOT-VALUE in the
spec.  KMP-CONDITION-SYSTEM:SLOT-VALUE will be EQ CLOS:SLOT-VALUE in
Lisp implementations which include a CLOS implementation.

Please note that I am in no way trying to deprecate acceptance or usage
of CLOS -- I want to see it as an integral part of Common Lisp
(especially if define-method-combination worked properly by using
closures instead of manipulating list structure... :-)

      Permit multiple parent-types to be named in the list of
      parent types. Define that these parent types are treated the
      same as the superior class list in a CLOS DEFCLASS expression.

You should explicitly state that the class precedence list is computed
in the way CLOS specifies.

      Extend the syntax for a slot in a DEFINE-CONDITION as follows...

       - If a symbol is used, DEFINE-CONDITION will by special case
	 treat this as if (symbol :INITARG keyword :READER reader-name)
	 were specified instead, where KEYWORD is generated by
	    (INTERN (SYMBOL-NAME symbol) (FIND-PACKAGE "KEYWORD"))
	 and reader-name is generated by
	    (INTERN (FORMAT NIL "~A-~A" condition-type symbol))
	 for CONDITION-TYPE being the condition type being defined.

       - A length 1 list, (symbol), is treated the same as providing
	 the symbol itself.

       - If a length 2 list, (symbol value) is provided, it is treated
	 as (symbol :INITARG keyword :READER reader-name :INITFORM value),
	 with KEYWORD and READER-NAME being computed as above.

       - If a list of length greater than 2 is used, it is treated
	 the same as a CLOS slot-specifier. In that case, the :INITARG
	 and :READER options must be explicitly specified if desired.

I think that this is highly undesirable wording to place in the
specification (but then, it wouldn't be the first time I've thought
that.)

I really don't think that your Standard is entrenched far enough
that backwards compatibility is an issue in its definition.  Note that
whether individual ε1implementationsε0 wish to offer such a
backward-compatibility feature is a different matter.

DEFINE-CONDITION (like statice:define-entity-type...) should require the
use of the standard :INITFORM option.  I'm of two minds about whether
DEFINE-CONDITION should default the :INITARG.  I lean towards having it
do so, with the prosiso that the initarg be exactly the symbol, *NOT* a
keyword.  My reasons for this are as follows:

* I can't think of a single case in which it is undesirable for the
  caller of MAKE-CONDITION to be able to specify the value of a slot.
* Given that there exists a DEFINE-CONDITION macro (distinct from
  DEFCLASS) we might as well make it do things that are useful for
  conditions.  (While we're at it, we should make it support
  :required-initargs -- only 1/4 joking.)
  I think this argues for defaulting the :INITARG option.
* (intern ... (find-package "KEYWORD")) is just asking for disaster.
  Major disaster.  The sort of disaster which non-keyword initargs were
  invented to avoid in the first place.  Just Say No!
  (BTW, this doesn't pose much of a compatibility problem.  A
  backwards-compatible DEFINE-CONDITION can recognise
  slot-specifications of the obsolete forms <name> and (<name> <initform>)
  and default the :INITARG in these cases to the losing keyword.
  There remains the problem of (<name>)...)

      Functions such as SIGNAL, which take arguments of class names,
      are permitted to take class objects.

Presumably it is an error to pass something which is not a subclass of
CONDITION.

      Eliminate the :CONC-NAME option to DEFINE-CONDITION.

Strongly agreed.

      Define that condition reporting is mediated through the
      PRINT-OBJECT method for the condition type (class) in question,
      with *PRINT-ESCAPE* always being NIL. Specifying 
      (:REPORT fn) in the definition of a condition type C is
      equivalent to doing
       (DEFMETHOD PRINT-OBJECT ((X c) STREAM)
	 (IF *PRINT-ESCAPE* (CALL-NEXT-METHOD) (fn X STREAM)))

I think that this is a very bad move.
A much better idea is the define something like DBG:REPORT, which is
only called in the PRINC case.  Otherwise every time a user wants to
write a method to affect the way a condition reports itself she must go
through the (if *print-escape* (call-next-method) ...) crap.

I suggest
(defgeneric report-condition (condition stream &key verbosely))

[BTW the reason for the :VERBOSELY keyword is in case you have ever seem
the error messages from ILA-NFS -- there is no way to control whether
they print a dozen lines explaining every possible conceivable cause of
the problem (which is appropriate when the debugger is entered, for
example) or whether they should just summarise the problem (which is
appropriate when the ":Copy File" command reports that it was unable to
copy one particular file.)]

Having the :VERBOSELY keyword can't hurt anything, and it provides a way
to avoid horrible inappropriate verbosity.

Another reason for defining a new generic function and not reusing
PRINT-OBJECT is that that ε1doesε0 provide a way to add extra options like
:VERBOSELY.

    Examples:

     [...]

     Report methods ...

       (DEFMETHOD PRINT-OBJECT ((X OOPS) STREAM)
	 (IF *PRINT-ESCAPE* 
	     (CALL-NEXT-METHOD)
	     (FORMAT STREAM "Oops! Something went wrong.")))

I think this is a good example of the lossage I described above.

    [...]

    Discussion:

      People seem to disagree about the status that CLOS might occupy
      in the upcoming standard. In spite of a vote of support, they seem
      to think it might be optional in some way. Passing this proposal
      establishes a clear precedent for the full integration of CLOS into
      the emerging language.

As I said above, I completely agree with this.  However, the pragmatics
of the next year or so -- in which users will likely be offered
vendor-supported Error Standard implementations but not vendor-supported
CLOS -- argue for the sort of minor change I suggested above.

Finally, in <881006184006.0.KMP@BOBOLINK.SCRC.Symbolics.COM> you reply
to Gregor:

   Also, it's no different than what DEFSTRUCT does, so it's not like this
   is the only place in the language following those rules. Have you
   submitted a proposal to deprecate DEFSTRUCT?

I think this is a highly spurious argument.  There is no reason to prepetuate
the bad design of DEFSTRUCT.  (I have never heard anybody argue that the
mandatory default-value in defstruct slot syntax is anything but a
mistake.)


     ----- End Forwarded Messages -----