That sounds like a good way for it to work.

I'm not sure how safe it would be to depend on each
of the extant implementation of Common Lisp to
do this.  It would probably be best if they all
conformed; the only drawback would be the
tiny possibility that some code somewhere is
depending on the existing behavior.  One could
always use the old trick of having a compatibility
mode for the sake of applications that want
to move to the new release but whose developers
don't have time to fix the application "the right way".

-- Dan

Pascal Costanza wrote:
On 6 Jan 2011, at 18:03, Didier Verna wrote:

Daniel Weinreb wrote:

This conversation has been good.
 Yup. Here's what I gather from it, mostly:

- a shared slot's initform is required to be evaluated when the class is
 created,

I agree here.

- however, nothing tells us that the resulting value is used immediately
 to initialize the slot (it could just be stored somewhere), and
 implementations seem to be free to do so right now, or later when the
 first instance is created.

I disagree here. I think the only valid time to initialize a shared slot is 
when the first instance of the class in question is initialized, using either 
an explicitly passed value via an :initarg or :default-initargs option, or 
using the most recently provided :initform. What the CLOS MOP says about 
class-prototype is not binding in this case, according to the HyperSpec the 
only way to initialize instances of user-defined classes is by way of 
initialize-instance, reinitialize-instance and/or shared-initialize. This 
usually happens implicitly as an effect of calling make-instance.

This effectively means the following:

- When a class is defined for the first time, the :initform for a shared slot 
needs to be evaluated immediately, and its result must be stored in some 
temporary memory location. (There is no notion of first-class dynamic 
environments in Common Lisp, so there is no other way of ensuring that the 
:initform can be evaluated in the correct dynamic environment.)

- When a class is redefined before the first instance of that class is 
initialized, the :initform for a shared slot needs to be reevaluated and the 
result stored in that temporary memory location, possibly overriding a 
previously stored result of an initform.

- When a class is redefined after the first instance of that class is 
initialized, the :initform for a shared slot can be ignored, because that 
shared slot is already initialized.

- When the first instance of a class is initialized, the shared slots can be 
initialized with the values stored in the temporary memory locations for the 
results of the initforms, which can in turn be discarded.

So, effectively, a shared slot behaves like defparameter before the first 
instance of a class is initialized, and like defvar afterwards. This is pretty 
insane. It would have been easier and more straightforward if there had been a 
:reinitialize slot option for shared slots which, if true, makes it behave like 
defparameter, and if false, makes it behave like defvar. That would have been 
unambiguous semantics.

There is no real advantage in having shared slots over global special 
variables. On top of that, the slot access protocols in the CLOS MOP also don't 
work that well in conjunction with shared slots. So it's better to avoid them. 
Fortunately, this is the only feature in CLOS that doesn't make any sense, as 
far as I can tell.


Pascal

_______________________________________________
pro mailing list
pro@common-lisp.net
http://common-lisp.net/cgi-bin/mailman/listinfo/pro

Reply via email to