From: Pascal C. <pc...@p-...> - 2005-11-07 07:33:51
|
Hi, SBCL doesn't seem to perform any checks on the :allocation kind of a given slot. At least, the following code is accepted without any hint that something might be wrong: (defclass test () ((slot :allocation :foo))) (defparameter *p* (make-instance 'test)) Is this intentional? Pascal -- Pascal Costanza, mailto:pc...@p-..., http://p-cos.net Vrije Universiteit Brussel, Programming Technology Lab Pleinlaan 2, B-1050 Brussel, Belgium |
From: Nikodemus S. <tsi...@cc...> - 2005-11-07 09:09:11
|
On Mon, 7 Nov 2005, Pascal Costanza wrote: > (defclass test () > ((slot :allocation :foo))) > > (defparameter *p* (make-instance 'test)) > > Is this intentional? Without looking at the code, I'd say both yes and no. My recollection is the bit of the DEFCLASS code that is responsible for this stuff is rather naive, and skips the check so that custom allocation options will be accepted -- instead of checking with the metaclass. Definitely suboptimal. I'll add this to BUGS. Cheers, -- Nikodemus Schemer: "Buddha is small, clean, and serious." Lispnik: "Buddha is big, has hairy armpits, and laughs." |
From: Christophe R. <cs...@ca...> - 2005-11-07 09:31:50
|
Pascal Costanza <pc...@p-...> writes: > SBCL doesn't seem to perform any checks on the :allocation kind of a > given slot. At least, the following code is accepted without any hint > that something might be wrong: > > (defclass test () > ((slot :allocation :foo))) > > (defparameter *p* (make-instance 'test)) > > Is this intentional? I think so. (Well, it wasn't directly intentional but I think it follows as a logical consequence of supporting custom allocation). I had to sit and stare a bit before I realised that the make-instance not only causes the slot definition to be created with :allocation :foo, which is fine, but instantiates a slot, which is less obviously fine. On the other hand, what would :allocation :none look like? I claim that an implementation of slots with no space for values looks much like the above, and an error should be signalled only when attempting to read or write such slots. If there's something in AMOP which says that standard slot definitions' allocation can only be :instance or :class, then obviously this has to be revised (and users wishing to implement :allocation :none will have to implement a bit more of the protocol themselves), but the late-binding nature of the MOP makes it hard to say exactly when something is definitely wrong. Maybe this rather esoteric use of the absence of methods should be required to use custom slot definition classes, but this feels a bit like an (ARRAY NIL) situation -- maybe unintended consequences, but apparently legal. Lest anyone think these slots are completely useless, SLOT-EXISTS-P and (the negation of) SLOT-MISSING can both be made to do useful things... Cheers, Christophe |
From: Pascal C. <pc...@p-...> - 2005-11-07 11:59:52
|
On 7 Nov 2005, at 10:31, Christophe Rhodes wrote: > Pascal Costanza <pc...@p-...> writes: > >> SBCL doesn't seem to perform any checks on the :allocation kind of a >> given slot. At least, the following code is accepted without any hint >> that something might be wrong: >> >> (defclass test () >> ((slot :allocation :foo))) >> >> (defparameter *p* (make-instance 'test)) >> >> Is this intentional? > > I think so. (Well, it wasn't directly intentional but I think it > follows as a logical consequence of supporting custom allocation). > > I had to sit and stare a bit before I realised that the make-instance > not only causes the slot definition to be created with :allocation > :foo, which is fine, but instantiates a slot, which is less obviously > fine. On the other hand, what would :allocation :none look like? I > claim that an implementation of slots with no space for values looks > much like the above, and an error should be signalled only when > attempting to read or write such slots. > > If there's something in AMOP which says that standard slot > definitions' allocation can only be :instance or :class, then > obviously this has to be revised (and users wishing to implement > :allocation :none will have to implement a bit more of the protocol > themselves), but the late-binding nature of the MOP makes it hard to > say exactly when something is definitely wrong. I think a good place to check for the :allocation option is in direct- slot-definition-class, which could look as follows: (defmethod direct-slot-definition-class ((class standard-class) &rest initargs &key allocation) (when (eq (class-of class) (find-class 'standard-class)) (unless (member allocation '(:class :instance)) (error "Unexpected :allocation option ~S." allocation))) ...) This should be sufficient for the following reasons: - The only way to do something useful with new allocation kinds is to create a new subclass of standard-effective-slot-definition and define methods on the slot-xxx-using-class functions. - The only way to ensure that a new effective slot definition class is used is by defining a method on effective-slot-definition-class which must be specialized on a new class metaobject class. So a new class metaobject class is necessary to provide new allocation kinds. Therefore, it is sufficient when the MOP checks whether the class is exactly the standard-class, and in that case perform the check for :class or :instance. I may be missing something, but I am pretty sure this is sound. Pascal -- Pascal Costanza, mailto:pc...@p-..., http://p-cos.net Vrije Universiteit Brussel, Programming Technology Lab Pleinlaan 2, B-1050 Brussel, Belgium |
From: Christophe R. <cs...@ca...> - 2005-11-07 12:30:55
|
Pascal Costanza <pc...@p-...> writes: > This should be sufficient for the following reasons: > > - The only way to do something useful with new allocation kinds is to > create a new subclass of standard-effective-slot-definition and > define methods on the slot-xxx-using-class functions. This turns out not to be true, I think: see mop-1.impure-cload.lisp in sbcl's tests/ subdirectory. It may be that the code in there is bad MOP style in some sense, but I don't think it is prohibited either by ANSI or by AMOP... Cheers, Christophe |
From: Pascal C. <pc...@p-...> - 2005-11-07 16:25:21
|
On 7 Nov 2005, at 13:30, Christophe Rhodes wrote: > Pascal Costanza <pc...@p-...> writes: > >> This should be sufficient for the following reasons: >> >> - The only way to do something useful with new allocation kinds is to >> create a new subclass of standard-effective-slot-definition and >> define methods on the slot-xxx-using-class functions. > > This turns out not to be true, I think: see mop-1.impure-cload.lisp in > sbcl's tests/ subdirectory. It may be that the code in there is bad > MOP style in some sense, but I don't think it is prohibited either by > ANSI or by AMOP... OK, here is a correction: The only way to do something useful with new allocation kinds is to define methods on the slot-xxx-using-class functions. Either their class arguments have to be specialized on a new class object metaclass, or their slot definition arguments have to be specialized on a new slot definition metaobject class, or both. (It's actually better to specialize both because then a CLOS implementation can do more optimizations, but that's besides the point.) In both cases, a new class metaobject class is required. When the class arguments are specialized this is obvious. When the slot definition arguments are specialized, they must be specialized on classes returned by effective-slot-definition-class in order to have a useful effect, which in turn requires a specialization on a new class metaobject class. So a check for :allocation kinds in direct-slot-definition-class, as described in my previous posting, should be sufficient because it will also see class metaobjects of that class metaobject class. Better? ;) Pascal -- Pascal Costanza, mailto:pc...@p-..., http://p-cos.net Vrije Universiteit Brussel, Programming Technology Lab Pleinlaan 2, B-1050 Brussel, Belgium |
From: Christophe R. <cs...@ca...> - 2005-11-07 16:35:52
|
Pascal Costanza <pc...@p-...> writes: > So a check for :allocation kinds in direct-slot-definition-class, as > described in my previous posting, should be sufficient because it > will also see class metaobjects of that class metaobject class. > > Better? ;) It's still not watertight, I think, though I'm really pushing the boundaries... can't you CHANGE-CLASS the class metaobject in between creation of the class and creation of the first instance of that class? Cheers, Christophe |
From: Christophe R. <cs...@ca...> - 2005-11-07 16:59:10
|
Christophe Rhodes <cs...@ca...> writes: > Pascal Costanza <pc...@p-...> writes: > >> So a check for :allocation kinds in direct-slot-definition-class, as >> described in my previous posting, should be sufficient because it >> will also see class metaobjects of that class metaobject class. >> >> Better? ;) > > It's still not watertight, I think, though I'm really pushing the > boundaries... can't you CHANGE-CLASS the class metaobject in between > creation of the class and creation of the first instance of that > class? Aha, no you can't! AMOP says: Portable programs must not call change-class to change the class of any class metaobject or to turn a non-class object into a class metaobject. OK, maybe your argument holds, then :-) Cheers, Christophe |
From: Pascal C. <pc...@p-...> - 2005-11-07 17:05:18
|
On 7 Nov 2005, at 17:35, Christophe Rhodes wrote: > Pascal Costanza <pc...@p-...> writes: > >> So a check for :allocation kinds in direct-slot-definition-class, as >> described in my previous posting, should be sufficient because it >> will also see class metaobjects of that class metaobject class. >> >> Better? ;) > > It's still not watertight, I think, though I'm really pushing the > boundaries... can't you CHANGE-CLASS the class metaobject in between > creation of the class and creation of the first instance of that > class? You are not allowed to do that. See "Initialization of Class Metaobjects" in AMOP: "Portable programs must not call change-class to change the class of any class metaobject or to turn a non-class object into a class metaobject." The only case in which CHANGE-CLASS is used on a class metaobject is when a FORWARD-REFERENCED-CLASS is changed into some other class metaobject class. See ensure-class-using-class: "If the class argument is a forward referenced class, change-class is called to change its class to the value specified by the :metaclass argument. The class metaobject is then reinitialized with the previously computed initialization arguments. (This is a documented violation of the general constraint that change-class not be used with class metaobjects.)" This effectively means that reinitialize-instance is called in this case, so slot definition metaobjects will be recomputed. (There was a suggestion in some paper to allow CHANGE-CLASS to be called before a class is first finalized, but I guess it would make sense to specify that in those cases the class should also be reinitialized for various reasons.) Still not watertight? ;) Pascal -- Pascal Costanza, mailto:pc...@p-..., http://p-cos.net Vrije Universiteit Brussel, Programming Technology Lab Pleinlaan 2, B-1050 Brussel, Belgium |