[Openmcl-devel] Bug or spec change?

Shannon Spires svs at bearlanding.com
Fri Mar 5 10:24:22 PST 2021


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 
> <mailto: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/c10ce9ad/attachment.htm>


More information about the Openmcl-devel mailing list