From: Kenny Tilton
Subject: Re: Newbie: Ensuring a Required Argument for Constructor?
Date: 
Message-ID: <3C48A878.E02A76D4@nyc.rr.com>
Steve Haflich wrote:
> 
>    From: Kenny Tilton <·······@nyc.rr.com>
> 
> Are we are continuing this privately by email, not on c.l.l.?

No, that was just a dumb mistake on my part. :) 


> steve:
>    > Please explain why you think this is a misinterpretation of the MOP.
>    > I would agree that the behavior is apparently unspecified by the ANS,
> kenny:
>    agreed
> 
> 
>    > ensure-class-using-class is explicit that when the class already exists,
>    > it is reinitialized by calling reinitialize-instance with the
>    > canonicalized arguments from the new defclass form.  Therefore if the
>    > :default-initargs argument was _not_ present ...
> 
>    agreed also. Franz actually entered the fray on cll last time this came
>    up.
> 
>    The issue is whether the semantics of ensure-class-using-class should
>    necessarily be the semantics of defclass. I think not, and if not there
>    is no point in talking about e-c-u-c.
> 
> In the Concepts chapter of the MOP (5.4.2 The defclass Macro, p.146 in
> the printed book, but also in the online version) see Figure 5.1 

That does not help, it /has/ definitarg coded. But Figure 5.2 does
support your interpretation: no definitarg, no corresponding initarg to
ensure-class. However...

> which
> shows a defclass form ... and an expansion of it that would result in
> the proper call to ensure-class.  I feel this example, coupled with
> the other citations I made, leaves little room for doubt.  See also
> p.149.

Well that's the problem: "The default initargs class option, if it is
present in the defclass form, becomes the value of the
:direct-default-initargs keyword argument to ensure-class. "

If it is not present? Silent, except for the accident of how figure 5.2
was coded. I say 'accident' just to emphasize: "that's no way to specify
semantics".

But if there is /any/ support for either interpretation in the MOP, I
agree Fig. 5.2 is it. I had not noticed that before.

kenny
clinisys

From: Steven M. Haflich
Subject: Re: Newbie: Ensuring a Required Argument for Constructor?
Date: 
Message-ID: <3C48BBFF.6D21C189@franz.com>
Kenny Tilton wrote:

> Steve Haflich wrote:

> That does not help, it /has/ definitarg coded. But Figure 5.2 does
> support your interpretation: no definitarg, no corresponding initarg to
> ensure-class. However...
> 
> > which
> > shows a defclass form ... and an expansion of it that would result in
> > the proper call to ensure-class.  I feel this example, coupled with
> > the other citations I made, leaves little room for doubt.  See also
> > p.149.
> 
> Well that's the problem: "The default initargs class option, if it is
> present in the defclass form, becomes the value of the
> :direct-default-initargs keyword argument to ensure-class. "

The reason treatment of this particular keyword is spelled out is that
unlike other class options, the name is different from the class
metaobject reader:  default-initargs /= direct-default.

> If it is not present? Silent, except for the accident of how figure 5.2
> was coded. I say 'accident' just to emphasize: "that's no way to specify
> semantics".

Ah, but it is spelled out by something I cited earlier: The "Initialization
of Class Metaobjects" section in the MOP dictionary, found near the bottom
of p.193 in the printed book:

  Unless there is a specific note to the contrary, then during
  reinitialization, if an initialization argument is not supplied,
  the previously stored value is left unchanged. 

Since it was not otherwise mentioned, the treatment of this class
option is _explicitly_ covered by this clause.  The metaclass option
is another example -- it is sticky if not overridden in a class
redefinition.

<14> (defclass frob-class (standard-class) ())
#<standard-class frob-class>
<15> (defclass frob () () (:metaclass frob-class))
#<frob-class frob>
<16> (defmethod initialize-instance :after ((f frob) &key arg)
      (format t "arg=~a~%" arg))
#<standard-method initialize-instance :after (frob)>
<17> (make-instance 'frob)
arg=nil
#<frob @ #x307233ba>
<18> (defclass frob () () (:default-initargs :arg (random 100)))
#<frob-class frob>			; The metaclass was not
					; specified, but remained
					; unchanged!
<19> (make-instance 'frob)
arg=91
#<frob @ #x30723cca>
<20> (defclass frob () () (:metaclass frob-class))
#<frob-class frob>			; Now the default-initargs
<21> (make-instance 'frob)		; is sticky.
arg=30
#<frob @ #x30724412>

The way to remove the default-initarg specification is to provide it
explicitly nil, as you observed in your original message.

<22> (defclass frob () () (:default-initargs))
#<frob-class frob>
<23> (make-instance 'frob)
arg=nil
#<frob @ #x30724b0a>
From: Kenny Tilton
Subject: Re: Newbie: Ensuring a Required Argument for Constructor?
Date: 
Message-ID: <3C48D7BA.29765750@nyc.rr.com>
"Steven M. Haflich" wrote:
> 
> Kenny Tilton wrote:
> Ah, but it is spelled out by something I cited earlier: The "Initialization
> of Class Metaobjects" section in the MOP dictionary, found near the bottom
> of p.193 in the printed book:
> 
>   Unless there is a specific note to the contrary, then during
>   reinitialization, if an initialization argument is not supplied,
>   the previously stored value is left unchanged.

BEGIN LOOP (we are in)

That is not about defclass, that is about the internals you face
implementing defclass. your best argument (aside from the accident of
fig 5.2) is "why else would they specify that if they did not want
defclass to work that way?". By default reinitialize-instance would
restore direct-default-initargs to nil, but they are taking pains here
to specify ensure-class as overriding that.

But again, reading tea leaves is no way to specify the semantics of
defclass. And two CL vendors see it my way, two see it yours.

For me the tie-breaker is, what should be the semantics of defclass?
And, for me, if I first code:

(defclass money ()
  ((fast :initarg :fast :initform :yes))
  (:default-initargs :fast :no))

and then come to my senses and delete the :fast :no (and while I am at
it tidy up):

 (defclass money ()
   ((fast :initarg :fast :initform :yes)))

I certainly expect to make money fast and certainly do not expect to get
diff behavior from the morally identical:

(defclass money ()
  ((fast :initarg :fast :initform :yes))
  (:default-initargs))

END LOOP

kenny
clinisys
From: Pierre R. Mai
Subject: Re: Newbie: Ensuring a Required Argument for Constructor?
Date: 
Message-ID: <871ygmfh4n.fsf@orion.bln.pmsf.de>
Kenny Tilton <·······@nyc.rr.com> writes:

> That is not about defclass, that is about the internals you face
> implementing defclass. your best argument (aside from the accident of

In the AMOP, DEFCLASS is specified to work through ensure-class.
Furthermore, w.r.t. the :default-initargs argument to DEFCLASS, the
AMOP specifically specifies:

<quote AMOP, page 149, top half, emphasis mine, AMOP emphasis elided>
The _default initargs_ class option, *if it is present* in the
defclass form, becomes the value of the :direct-default-initargs
keyword argument to ensure-class.
</quote>

From context it is IMHO abundantly clear, that a missing default
initargs class option results in a missing :direct-default-initargs
option passed to ensure-class, with the known consequences, as
specified for ensure-class(-using-class).

> fig 5.2) is "why else would they specify that if they did not want
> defclass to work that way?". By default reinitialize-instance would
> restore direct-default-initargs to nil, but they are taking pains here
> to specify ensure-class as overriding that.

And defclass explicitly uses ensure-class.  The whole thing is not an
accident, it is rather clearly designed to be the way it is (this gets
very apparent if you look at the whole missing-argument vs. specified
nil argument distinctions being made all over the place, with very
few, explicit exceptions).  That you don't like that design is another
matter entirely.  I fail to see how the relevant passages of AMOP
support any other interpretation more than the given one.

> But again, reading tea leaves is no way to specify the semantics of
> defclass. And two CL vendors see it my way, two see it yours.

Then it is high time that bug reports are filed, in order for
implementations to come to some consensous.  FWIW, CMU CL sees it the
"Franz" way (independently), and we've corrected reported differences
to the AMOP in the treatment of :direct-superclasses and :direct-slots
by ensure-class(-using-class).  I've personally got conformance to
AMOP as an important goal, only surpassed by conformance to ANSI CL.

If there are different interpretations of AMOP, they need to be
brought out into the open, if we are to move forward w.r.t. AMOP as a
layered standard.

> For me the tie-breaker is, what should be the semantics of defclass?

There is no tie to be broken here.

> And, for me, if I first code:
> 
> (defclass money ()
>   ((fast :initarg :fast :initform :yes))
>   (:default-initargs :fast :no))
> 
> and then come to my senses and delete the :fast :no (and while I am at
> it tidy up):
> 
>  (defclass money ()
>    ((fast :initarg :fast :initform :yes)))
> 
> I certainly expect to make money fast and certainly do not expect to get
> diff behavior from the morally identical:
> 
> (defclass money ()
>   ((fast :initarg :fast :initform :yes))
>   (:default-initargs))

There is already precedent that that is not to be expected, cf. defvar:

(defvar *money-fast-p* :no)

Now change to

(defvar *money-fast-p* :yes)

and eval, but

*money-fast-p*

=> :no

Environments have built-in support to treat defvar in "eval-at-point"
situations as defparameter, and maybe they should have support for
defclass, etc. too.  But the AMOP is quite adament in what should
happen here (and in other similar cases).

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: Kenny Tilton
Subject: Re: Newbie: Ensuring a Required Argument for Constructor?
Date: 
Message-ID: <3C49A99F.ACD0AD4D@nyc.rr.com>
Hang on, I might be wrong. Bug reports may be in order. I said the spec
was silent on this issue. But weary of all this tea-reading, i put down
my AMOP and turned to CLHS and found:

   file:///D|/acl501/ansicl/subsecti/redefini.htm

"Redefining a class modifies the existing class object to reflect the
new class definition; it does not create a new class object for the
class."

If (1) I redefine a class definition as: (defclass money () ((fast
:initarg :fast :initform nil)))

and (2) I make-instance on that class and see any default initarg come
flying in

then (3) the existing class object does not reflect the new class
definition

and (4) the CL implementation I am using is non-conforming

QED?

kenny
clinisys