From: Paul F. Dietz
Subject: DEFINE-CONDITION questions
Date: 
Message-ID: <D--dnX0bTp6gCO-jXTWcoA@dls.net>
I'm reading through the CL Hyperspec page for DEFINE-CONDITION
and I'm getting confused.

The meaings of the slot options :writer, :accessor, and :allocation are not
defined anywhere.  Was there a transcription error from the paper ANSI CL
spec?

Also, the :writer slot option can have a function name of the form
(setf <symbol>), but the page also says 'The consequences are unspecified
if an attempt is made to assign the slots by using setf.'  So what use
is that (setf <symbol>) function name?

	Paul

From: Kent M Pitman
Subject: Re: DEFINE-CONDITION questions
Date: 
Message-ID: <sfwadfx9rll.fsf@shell01.TheWorld.com>
"Paul F. Dietz" <·····@dls.net> writes:

> I'm reading through the CL Hyperspec page for DEFINE-CONDITION
> and I'm getting confused.
> 
> The meaings of the slot options :writer, :accessor, and :allocation are not
> defined anywhere.  Was there a transcription error from the paper ANSI CL
> spec?

No.  If you read the original spec
 http://www.nhplace.com/kent/CL/Revision-18.txt
I think you'll see (I'm working from memory, so didn't check)
that define-condition had different syntax than it does now.
There was an early attempt to keep CLOS and the condition system
completely separate because we didn't know both would be adopted,
nor did we know that CLOS would be popular.  (A number of people
were very nervous about it.)  Later we voted to make define-condition
work more compatibly with defclass, but there was probably no actual
text voted.  I was (as editor) probably left to just conjure appropriate
text.  (There's probably a cleanup issue, but I don't remember what
it said and am off to bed now, so I leave that as an exercise to the
reader, too.) So maybe I was sloppy.

HOWEVER, if memory serves, we really wanted conditions to have a read-only
metaclass. I don't remember how far we got in that. I know we didn't
define the metaclass they should have. We ran out of time.  But I thought
we didn't allow :accessor and :writer because that would mean they were
not read-only; but maybe we didn't get to removing that either.

Not sure about :allocation and its fate.

> Also, the :writer slot option can have a function name of the form
> (setf <symbol>), but the page also says 'The consequences are unspecified
> if an attempt is made to assign the slots by using setf.'  So what use
> is that (setf <symbol>) function name?

Might be an incomplete attempt to readonlyify things.

If you're asking me? Don't assign the slots. Bad style.
Condition objects are intended to statically describe the condition,
not to be changed.  They are just structured versions of a message 
string; they are not a data store.
From: james anderson
Subject: Re: DEFINE-CONDITION questions
Date: 
Message-ID: <3E7308AC.C9282BC3@setf.de>
? what about the situation where conditions are used to describe things other
than non-continuable errors.?

the occasion may arise where it  would reasonable to compute some of the
description of the condition on the fly. things which are "expensive" to
compute, but might not be used if the condition is dismissed, ignored, and etc.
things which one would want to compute once only and cache? ona can always
delegate to work around the write prescription, but that's not a qualitative
difference.

...

Kent M Pitman schrieb:

> "Paul F. Dietz" <·····@dls.net> writes:

...

>
>
> If you're asking me? Don't assign the slots. Bad style.
> Condition objects are intended to statically describe the condition,
> not to be changed.  They are just structured versions of a message
> string; they are not a data store.
From: Kent M Pitman
Subject: Re: DEFINE-CONDITION questions
Date: 
Message-ID: <sfwadfwr4pi.fsf@shell01.TheWorld.com>
james anderson <··············@setf.de> writes:

> ? what about the situation where conditions are used to describe things other
> than non-continuable errors.?
> 
> the occasion may arise where it  would reasonable to compute some of the
> description of the condition on the fly. things which are "expensive" to
> compute, but might not be used if the condition is dismissed, ignored, and etc.
> things which one would want to compute once only and cache? ona can always
> delegate to work around the write prescription, but that's not a qualitative
> difference.
> 
> ...
> 
> Kent M Pitman schrieb:
> 
> > "Paul F. Dietz" <·····@dls.net> writes:
> 
> ...
> 
> >
> >
> > If you're asking me? Don't assign the slots. Bad style.
> > Condition objects are intended to statically describe the condition,
> > not to be changed.  They are just structured versions of a message
> > string; they are not a data store.

How many slots is your condition going to _have_?  I have never in my 
20 year experience with these things seen a condition with upward of
about 4 or 5 slots, but let's say ther are 20 slots just for purposes
of argument.  The purpose of conditions is 99% of the time to signal
them, and when you invoke the signalling mechanism you invoke some unknown
number of test functions on the stack which might or might not be willing
to handle them.   The speed cost of having to cons an object of size 20 is
just not that large compared to the potential speed cost of having to run,
potentially, 5-20 handlers in a typical case.  Those are typical "small
application" numbers; in large applications, I could imagine the number of
handlers on the stack growing but still not the number of slots.  People
ar mostly remarkably lazy about condition descriptions.

Add to this the fact that if you have 20 features that you want to pre-cons
you can put them in a single object and make that one object be a slot
in the condition, so that consing in the pre-consed 20 features is just
one cons, as in :machine-description *static-machine-model*
so that every time you do it, you get the same pre-consed machine model
at the cost of just filling one slot.

The reason you don't want to allow side-effects, IMO, is that you want
someone who has pre-cached a _solution_ to win.  The much bigger cost than
creating the description of the situation is, IMO, the creation of the
handler for the description.  The bigger savings than in signaling, IMO,
is in handling, which has much less to work with while trying to get a 
foothold.  There are possibly many things you have to check for, and if
you can speed things up by recognizing a condition you've seen before based
on its identity, you will get a big speed savings. But if you can side-effect
that condition, recognizing it based on identity becomes useless.
From: Lars Brinkhoff
Subject: Re: DEFINE-CONDITION questions
Date: 
Message-ID: <85r898bhiv.fsf@junk.nocrew.org>
Kent M Pitman <······@world.std.com> writes:
> when you invoke the signalling mechanism you invoke some unknown
> number of test functions on the stack

This may be a stupid question, but I'm not sure I understand the
meaning of "test functions on the stack" here.  Do you refer to all
the condition handler functions (as specified by handler-bind) in
effect at the point where the condition is signalled?
From: Kent M Pitman
Subject: Re: DEFINE-CONDITION questions
Date: 
Message-ID: <sfwof4clamz.fsf@shell01.TheWorld.com>
Lars Brinkhoff <·········@nocrew.org> writes:

> Kent M Pitman <······@world.std.com> writes:
> > when you invoke the signalling mechanism you invoke some unknown
> > number of test functions on the stack
> 
> This may be a stupid question, but I'm not sure I understand the
> meaning of "test functions on the stack" here.  Do you refer to all
> the condition handler functions (as specified by handler-bind) in
> effect at the point where the condition is signalled?

Yes, I was being sloppy in my terminology.  Handlers.  They may have to poke
and prod at the condition to see if it's one they are competent to handle.
From: james anderson
Subject: Re: DEFINE-CONDITION questions
Date: 
Message-ID: <3E73CAC6.BEDD2CCB@setf.de>
Kent M Pitman wrote:
> 
> james anderson <··············@setf.de> writes:
> 
> > ? what about the situation where conditions are used to describe things other
> > than non-continuable errors.?
> >
> > the occasion may arise where it  would reasonable to compute some of the
> > description of the condition on the fly. things which are "expensive" to
> > compute, but might not be used if the condition is dismissed, ignored, and etc.
> > things which one would want to compute once only and cache? ona can always
> > delegate to work around the write prescription, but that's not a qualitative
> > difference.
> >
> > ...
> >
> > Kent M Pitman schrieb:
> >
> > >
> > > If you're asking me? Don't assign the slots. Bad style.
> > > Condition objects are intended to statically describe the condition,
> > > not to be changed.  They are just structured versions of a message
> > > string; they are not a data store.
> 
> How many slots is your condition going to _have_?  ...
> ...   The speed cost of having to cons an object [...] is
> just not that large compared to the potential speed cost of having to run,
> potentially, 5-20 handlers in a typical case.  Those are typical "small
> application" numbers; in large applications, I could imagine the number of
> handlers on the stack growing but still not the number of slots.  People
> ar mostly remarkably lazy about condition descriptions.

the issue is neither the cost to cons the condition and nor the issues of
identity. 

in general, one of the properties which recommends conditions over
unstructured messages is that they support slot and method inheritance. yet,
as they are not specified to be standard-objects, the programmer cannot rely
on the same instantiation protocol as is standardized for make-instance. where
it is not possible to augment a condition's initial state, the programmer
cannot implement an instantiation protocol and they are restricted to binding
those things which can and must be know either in the environemnt in which the
condition class is defined or in the environment in which an instance is made.
that one is neither able to augment initialization arguments nor should one
modify slot values significantly compromises the benefits of classification.

[i note that the immediate adminition was "bad style", but there are
implementation which carry that a step further.]

why would a read-only metaclass be prefered to permitting the class definition
to specify whether a condition is mutable or not? where the slot declarations
specify readers only, the instances are immutable, where writers are present,
they are mutable.

my specific question arose from considering how a condition should convey
aspects of its description which derive from fairly large data structures with
dynamic extent - things which one would not want to copy when instantiating
every condition. where the data are used, it is likely to be necessary to copy
it, where it is not used, the initial reference suffices.

while it is true that the application could reproduce the condition with the
transformed data, and it is true that the data could be conveyed through a
subsidiary delegate instance, and it is true that the data could be conveyed
by binding a closure, and ..., it struck me that unmitigatedly immutable
conditions are a constraint which one must often work around in order to
achieve portablility rather than serving as an adequate medium to convey a
description of the circumsrtances which led to their creation.

> 
> Add to this the fact that if you have 20 features that you want to pre-cons
> you can put them in a single object and make that one object be a slot
> in the condition, so that consing in the pre-consed 20 features is just
> one cons, as in :machine-description *static-machine-model*
> so that every time you do it, you get the same pre-consed machine model
> at the cost of just filling one slot.

as noted above, the question does not concern repeated use of a single
cachable datum.
 
> 
> The reason you don't want to allow side-effects, IMO, is that you want
> someone who has pre-cached a _solution_ to win.

what is the relation between immutable condition instances and cached
responses? while there would be good reasons to not reuse a given instance
with different slot values, how would they bear on augmenting a given instance
with further information.

>                                                  The much bigger cost than
> creating the description of the situation is, IMO, the creation of the
> handler for the description.  The bigger savings than in signaling, IMO,
> is in handling, which has much less to work with while trying to get a
> foothold.  There are possibly many things you have to check for, and if
> you can speed things up by recognizing a condition you've seen before based
> on its identity, you will get a big speed savings. But if you can side-effect
> that condition, recognizing it based on identity becomes useless.

i hope my notes above have made clear that the identity issues are not related
to my question.

...
From: Tim Bradshaw
Subject: Re: DEFINE-CONDITION questions
Date: 
Message-ID: <ey3smtnsfio.fsf@cley.com>
* james anderson wrote:
> my specific question arose from considering how a condition should convey
> aspects of its description which derive from fairly large data structures with
> dynamic extent - things which one would not want to copy when instantiating
> every condition. where the data are used, it is likely to be necessary to copy
> it, where it is not used, the initial reference suffices.

I think that in order to make this not be just a silly theoretical
argument of the standard `if I wanted to do this kind of thing then it
would be hard for me', you should provide instances where this is
*actually a problem in real programs*.

--tim
From: james anderson
Subject: Re: DEFINE-CONDITION questions
Date: 
Message-ID: <3E74BBA8.7482DE47@setf.de>
Tim Bradshaw wrote:
> 
> ...
> 
> I think that in order to make this not be just a silly theoretical
> argument of the standard `if I wanted to do this kind of thing then it
> would be hard for me', you should provide instances where this is
> *actually a problem in real programs*.
> 
> --tim

the particular case has to do with conditions constructed and signaled by a parser.

should a parse fail, one useful aspect of the description is a snapshot of the
parser's state at the point where the parse fails - the text context in the
original document, the production stack, either nominally or in terms of
partial results. some of these are likely to be large intermediate data
structures which have dynamic extent.

in some cases a condition describes a situation which the application is
expected to correct or for which either the application or some remote,
centralized part of the parser is expected to determine whether the condition
should even be signaled. in these cases there are advantages both to defering
transforming "expensive" aspects of state into permanent data and to
centralizing the places where this is done. 

conditions which are immutable and do not partake of a standard instantiation
protocol preclude various obvious implementation approaches.

for example, it is not portable to allocate a condition instance without
providing slot values and to use that uninitialized instance as a typed marker
in a protocol to determine whether to even signal it. instead one must either
provide a complete condition, or provide an alternative marker, or provide a
functional interface to communicate the smae descriptions as the condition
already encapsulates.

for example, it is not portable to instantiate a condition with its slots
bound to preliminary data and to provide accessors which reifiy those slot
values which are actually used. instead one must displace any mutation to the
bound data.

for example, it is not portable to provide a generic initialization function
for conditions to decide how best to initialize them based on some combination
of parser state and application settings. instead one must provide the values
as disjoint initialization forms in the condition declaration and/or write
nominally distinct make-* functions to perform this.

none of these is *actually a problem*, but all of them are examples of
standard idioms for working with classified data. none of which is available
for working with conditions, so long as they are immutable.
 
...
From: Tim Bradshaw
Subject: Re: DEFINE-CONDITION questions
Date: 
Message-ID: <ey31y17f2or.fsf@cley.com>
* james anderson wrote:

> should a parse fail, one useful aspect of the description is a
> snapshot of the parser's state at the point where the parse fails -
> the text context in the original document, the production stack,
> either nominally or in terms of partial results. some of these are
> likely to be large intermediate data structures which have dynamic
> extent.

I'm fairly sure that I would do that by having a condition which had a
single PARSER-STATE slot and then a much hairier object there.  This
sounds like a clunky approach but I don't think it really is: in
particular you can arrange the class graph of the state object in such
a way that, for instance, initialisation &c happens how you want it
to, and the class graph of the condition object in such a way that it
indicates the right kind of problem, and these can be quite separate
requirements.  

In general I try to keep the state of a condition object as small as
possible - just enough so that you know what it is, and it can
describe itself usefully, while having any complicated data off in
some other object to the side.

The reason I do this is because I used not to (therefore writing stuff
which was likely technically non-portable, and in practice
non-portable to, say Lucid), and I found that my class graphs became
so complex I couldn't work out what was going on.  Factoring things
into condition types (is this a system or user error? is it fatal or
nonfatal? does it wrap some other error? and so on) and data types (is
this a parser state object? does it cache? &c) means I write programs
I can understand...

--tim
From: Paul F. Dietz
Subject: Re: DEFINE-CONDITION questions
Date: 
Message-ID: <Gs2dnXLxAqVM9-6jXTWcoA@dls.net>
Kent M Pitman wrote:

> If you're asking me? Don't assign the slots. Bad style.
> Condition objects are intended to statically describe the condition,
> not to be changed.  They are just structured versions of a message 
> string; they are not a data store.

Thanks.  I'm writing compliance tests, so I'll leaving out tests of
:writer, :accessor, and :allocation.

A few other questions:

The slot-name has a non-CLOS syntax:

    a slot name (a symbol), the list of a slot name, or the list of
    slot name/slot form pairs.

Since there's a paragraph describing this, I assume this must be
accepted.  Is that right, or did :initform make this obsolete?

Also, the :documentation slot option is mentioned, but the syntax
only has a :documentation option for the entire condition.  Should
there be both?  If not, which one should there be?

	Paul;