[Openmcl-devel] OpenMCL MOP Issue

Gary Byers gb at clozure.com
Sun Feb 18 08:08:24 UTC 2007

On Sat, 17 Feb 2007, Brent Fulgham wrote:

> Gary,
> Thanks for the explanation, but I'm still confused by the first part of your 
> response:
> On Feb 17, 2007, at 5:07 PM, Gary Byers wrote:
>> (defclass foo ()
>> ((a :type (member 12 17 21))))
>> (defclass bar (foo)
>> ((a  :type (member 9 17 23))))
>> (slot-definition-type (car (class-direct-slots (find-class 'bar))))
>> => (member 9 17 23)
>> (slot-definition-type (car (class-slots (find-class 'bar))))
>> => (integer 17 17)
>> The (effective) type of a slot is the intersection of its direct type
>> and the direct types it inherits from its ancestors.  There are
>> several (an infinite number of ...) equivalent ways of specifying this
>> type in the example:
>> (and (member 12 17 21) (member 9 17 23))
>> (eql 17)
>> (satisfies 17p)
>> etc.
>> but it's a computed value that may or may not be EQL to the 
>> direct-slot-definition's TYPE.
> Coming from my admittedly rudimentary Lisp background, I am somewhat 
> surprised that this:
> ? (defclass b ()
>    ((foo :type boolean)))
> ... reports itself as this:
> ? (slot-definition-type (first (class-slots (find-class 'b))))
> ... even though the '"type" was explicitly declared as 'boolean'.
> Consider a type enclosing a larger set:
> ? (defclass a ()
> ((foo :type integer)))
> ? (slot-definition-type (first (class-slots (find-class 'a))))
> This makes sense to me, because the type 'integer is what I stipulated for 
> the slot; I don't expect to see a return type defining the list of values, 
> for example
> (MEMBER 0 1 2 3 4 ... )
> Is it just BOOLEAN that is defined as its two potential values, or are there 
> other types that work this way?

I'm not sure if there are good tutorials on the CL type system available
online or elsewhere.  (The presentation in CLtL[1|2] is probably less dry
than that in CLHS.)

Consider the case (like your original example) of:

(defclass foo ()
  ((a :type boolean)))

There are several different but equivalent ways of referring to "the
built-in type that contains T and NIL, exactly".

BOOLEAN is one way of referring to that type.

(MEMBER T NIL) is another way.

(OR (EQL T) (EQL NIL)) is yet another way.

(AND BOOLEAN) and (AND (MEMBER T NIL)) are still other ways.

Since classes are type-specifiers, the builtin class BOOLEAN (the value
returned by (FIND-CLASS 'BOOLEAN)) can also be used to refer to this type.

In general, the type of a slot in an EFFECTIVE-SLOT-DEFINITION is the
intersection of the type specified in the DIRECT-SLOT-DEFINITION (or
the DEFCLASS form) and the types of any inherited slots with the same
CLHS 7.5.3) That intersection is a -computed- value; in the case where there
are no inherited slot definitions, it's equivalent to (AND <type>) , or
(AND BOOLEAN) in the original example.  As we saw above, (AND BOOLEAN)
is equivalent to BOOLEAN, so BOOLEAN would be a correct result. 
(AND BOOLEAN) is also equivalent to (MEMBER T NIL), so that's also
a correct result.

I don't think that there's any reason to think that any correct result
is more correct than any other correct result, or that the type of
the effective slot has to be specified in exactly the same way that
it was specified in the DEFCLASS form/direct slot definition; there's
neither any reason for COMPUTE-EFFECTIVE-SLOT-DEFINITION to to do this 
nor any reason not to in the case where there are no inherited slots.

More information about the Openmcl-devel mailing list