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