[Openmcl-devel] Bug or spec change?

Ron Garret ron at flownet.com
Fri Mar 5 11:16:40 PST 2021


I stand corrected.

On Mar 5, 2021, at 10:24 AM, Shannon Spires <svs at bearlanding.com> wrote:

> See comments inline.
> -SS
> 
> On 3/5/21 9:25 AM, Ron Garret wrote:
>> 
>> On Mar 4, 2021, at 10:50 PM, Shannon Spires <svs at bearlanding.com> wrote:
>> 
>>> > So it makes no sense to create an instance of COUNTED-CLASS which inherits from RECTANGLE.
>>> 
>>> Sure it does.
>> 
>> No, it doesn’t :-)
>> 
>>> Any given class metaobject has two kinds of relationships with other class metaobjects: It has an INSTANCE-OF relationship with its metaclass and an ISA (or INHERITANCE) relationship with its superclasses.
>> 
>> Yes.
>> 
>>> The equivalent (and more conventional) definition of counted-rectangle would be
>>> 
>>> (defclass counted-rectangle (rectangle)
>>>   ()
>>>   (:metaclass counted-class))
>>> 
>>> and this makes perfect sense.
>> 
>> Yes.  And it works:
>> 
>>> Welcome to Clozure Common Lisp Version 1.11-r16812M  (DarwinX8664)!
>>> ? (defclass counted-class (standard-class)
>>>    ((counter :initform 0)))
>>> #<STANDARD-CLASS COUNTED-CLASS>
>>> ? (defclass counted-rectangle (rectangle)
>>>   ()
>>>   (:metaclass counted-class))
>>> #<COUNTED-CLASS COUNTED-RECTANGLE>
>>> ?
> 
> You haven't shown the definition of rectangle above. Let's include that:
> 
> Clozure Common Lisp Version 1.12-dev (v1.12-dev.5-22-g0430f8db) DarwinX8664
> 
> For more information about CCL, please see http://ccl.clozure.com.
> 
> CCL is free software.  It is distributed under the terms of the Apache
> Licence, Version 2.0.
> ? (defclass counted-class (standard-class)
>    ((counter :initform 0)))
> #<STANDARD-CLASS COUNTED-CLASS>
> ? (defclass rectangle ()
>     ((height :initform 0.0 :initarg :height)
>      (width :initform 0.0 :initarg :width)))
> #<STANDARD-CLASS RECTANGLE>
> ? (defclass counted-rectangle (rectangle)
>   ()
>   (:metaclass counted-class))
> > Error: The class #<STANDARD-CLASS RECTANGLE> was specified as a
> >        super-class of the class #<COUNTED-CLASS COUNTED-RECTANGLE>;
> >        but the meta-classes #<STANDARD-CLASS STANDARD-CLASS> and
> >        #<STANDARD-CLASS COUNTED-CLASS> are incompatible.
> > While executing: #<CCL::STANDARD-KERNEL-METHOD CCL::ENSURE-CLASS-INITIALIZED (CCL::SLOTS-CLASS)>, in process Listener(4).
> > Type cmd-. to abort, cmd-\ for a list of available restarts.
> > Type :? for other options.
> 1 > 
> 
> Oops. It doesn't work if rectangle's definition doesn't include (:metaclass counted-class).
> 
> But your point is valid because I didn't test for the case of defining rectangle after defining counted-rectangle. That works even when rectangle does not include (:metaclass counted-class). The order of class definitions shouldn't matter; I think that's probably a bug.
> 
>> But that is not the same thing as creating “an instance of COUNTED-CLASS which inherits from RECTANGLE”:
>> 
>>> ? (class-of (find-class 'counted-rectangle))
>>> #<STANDARD-CLASS COUNTED-CLASS>
>>> ? (class-direct-superclasses *)
>>> (#<STANDARD-CLASS STANDARD-CLASS>)
>>> ? 
>> 
>> In this case, COUNTED-CLASS inherits only from STANDARD-CLASS, not from RECTANGLE.  And that does indeed make sense.
> 
> This is where it's important to use precise terminology.
> 
> COUNTED-RECTANGLE is literally "The class metaobject named COUNTED-RECTANGLE which happens to be an instance of COUNTED-CLASS, and which also happens to inherit from RECTANGLE."  This makes perfect sense when one understands that COUNTED-RECTANGLE is a class metaobject, because only class metaobjects can "inherit" from anything. (Ordinary CLOS objects that are not class metaobjects cannot "inherit" from anything. They are merely instances of a single class, period. Although we might loosely say things like "the LION named Sam inherits from CARNIVORE and SAVANNAH-RESIDENT" that phrasing is not technically accurate; only the class LION can inherit from CARNIVORE and SAVANNAH-RESIDENT. As an instance of LION, Sam has no "inheritance" relationship with anything (except perhaps his ancestor lions, but that's not the kind of "inheritance" we're talking about here.))
> 
> The :direct-superclasses argument in the AMOP example specifies the inheritance relationship for class metaobjects. It expresses the same thing as (rectangle) below:
> 
> (defclass counted-rectangle (rectangle)
>   ()
>   (:metaclass counted-class))
> 
> Which again makes perfect sense.
> 
>>> What doesn't work in the example is that rectangle and counted-rectangle have different metaclasses.
>> 
>> No, that’s not the problem.  In the example as you’ve given it (not as the MOP book gives it), COUNTED-RECTANGLE has a metaclass of COUNTED-CLASS, and RECTANGLE (assuming you define it as the MOP book does) has a meta-class of STANDARD-CLASS.  And all that works just fine.
> 
> It only works if you define RECTANGLE after COUNTED-RECTANGLE. Which I think is probably a bug.
> 
>> 
>> The problem with the MOP example:
>> 
>>> ? (setf (find-class 'counted-rectangle)
>>>        (make-instance 'counted-class
>>>          :name 'counted-rectangle
>>>          :direct-superclasses (list (find-class 'rectangle))
>>>          :direct-slots ()))
>> 
>> Is that it is trying to make the metaclass of COUNTED-CLASS be RECTANGLE, and that doesn’t work because RECTANGLE is not a metaclass,
> 
> Nope. Again, :direct-superclasses is about the superclasses of the class metaobject; it is not about the metaclass of the class metaobject.
> 
> 
>>> Any time class A inherits from class B, they both should be instances of the same metaclass.
>> 
>> That is correct, but you’ve misapplied the rule.  The problem is not that "rectangle and counted-rectangle have different metaclasses”.  The problem in this case is that RECTANGLE and *COUNTED-CLASS* (not counted-rectangle) have different metaclasses.  Having rectangle and counted-rectangle have different metaclasses works perfectly well, as the example above demonstrates.
>> 
>> Another way to illustrate what the problem actually is here:
>> 
>> ? (typep (make-instance 'standard-class) 'class)
>> T
>> ? (typep (make-instance 'counted-class) 'class)
>> T
>> ? (typep (make-instance 'rectangle) 'class)
>> NIL
>> 
>> That is the reason that it makes no sense for RECTANGLE to be a DIRECT-SUPERCLASS of an instance of COUNTED-CLASS.  An instance of COUNTED-CLASS is a class, but an instance of RECTANGLE is not.  So an instance of the resulting chimera would have to be both a class and not a class.
>> 
>> But yeah, it gets pretty confusing.
>> 
>> rg
>> 
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.clozure.com/pipermail/openmcl-devel/attachments/20210305/cca56186/attachment.htm>


More information about the Openmcl-devel mailing list