[Openmcl-devel] OpenMCL MOP Issue

Gary Byers gb at clozure.com
Sun Feb 18 01:07:49 UTC 2007

(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)


but it's a computed value that may or may not be EQL to the 
direct-slot-definition's TYPE.

In the case where the slot isn't inherited, the effective slot's type
and the direct slot's type are equivalent, but I see nothing in AMOP
or CLHS that insists that the specifiers used to denote those
equivalent types be EQL in that case, and I certainly see nothing
that insists that if a SYMBOL is used in the direct-slot-definition
or the DEFCLASS form that that same symbol be used to denote the
effective slot's type.

(In MCL's case, the effective slot definition's type would have
been exactly the same as the direct slot definition's type; the
same bug was present in some older versions of OpenMCL.)

As far as (TYPE-OF T) being BOOLEAN rather than SYMBOL, CLHS says:

  "For any object that is an element of some built-in type:

     a. the type returned is a recognizable subtype of that built-in type.

     b. the type returned does not involve and, eql, member, not, or,
     satisfies, or values."

The ANSI test suite distributed with GCL interprets this to mean that
TYPE-OF's return value must be a subtype of all built-in types of
which its argument is a member. (It's not obvious to me that
that's what the passage above says; another interpretation is that
TYPE-OF could simply choose to return a subtype of "some" built-in
type of which its argument is a member, as long as that return
value satisfies other constraints.)

SINCE T is a member of the builtin types BOOLEAN and SYMBOL and since
BOOLEAN is a subtype of SYMBOL (but not vice versa), BOOLEAN is a
correct answer and SYMBOL is not under the test suite's interpretation.
In this case, I don't believe that there is any other correct answer
under the test suite's interpretation, and BOOLEAN is clearly a correct
answer under the other interpretation

In many cases (notably involving NUMBERs and ARRAYs in either interpretation
and involving T in ), there are many correct answers.  Idioms like

(eq (type-of x) expected)

should generally be avoided or viewed with suspicion.

On Sat, 17 Feb 2007, Brent Fulgham wrote:

> I'm summarizing an e-mail exchange I had with Alexander Repenning off-list a 
> couple of weeks ago.  I was hoping someone (read: Gary!) might have some 
> ideas on how to approach this problem, or perhaps counterexamples of why 
> OpenMCL's current behavior is correct.
> The XMLisp (http://www.agentsheets.com/lisp/XMLisp/) library seems to have 
> some problems on OpenMCL (at least the 1.1 version, I have not tried it with 
> 1.0).  It appears to have fundamental differences in the way it works 
> compared to MCL and LispWorks.
> Alexander traced it down to the following apparent type problem:
> (defclass a ()
>  ((foo :type symbol)))
> (slot-definition-type (first (class-slots (find-class 'a))))
> or
> (defclass c ()
>  ((foo :type array)))
> (slot-definition-type (first (class-slots (find-class 'c))))
> -> ARRAY
> (defclass b ()
>  ((foo :type boolean)))
> (slot-definition-type (first (class-slots (find-class 'b))))
> MCL & LispWorks -> BOOLEAN
> This is a problem.  (MEMBER T NIL) is a valid type definition but it is 
> really hard to further process this. We are using this type information in 
> XMLisp to implement CODECs, e.g.,
> (defmethod PRINT-TYPED-ATTRIBUTE-VALUE (Value (Type (eql 'boolean)) Stream)
> (prin1 (if Value "true" "false") Stream))
> At least according to the MOP spec one would think slot-definition-type 
> returning something like BOOLEAN instead of (MEMBER T NIL) would be the 
> preferred / correct way?
> # Generic Function slot-definition-type slot the
> # Returns the type of slot. This is a type specifier name. This is the 
> defaulted value of the :type initialization argument that
> # was associated with the slot definition metaobject during initialization.
> To make the type dispatchable with the kind of method above, the type 
> information needs to be a symbol.  Not sure if CLTM has any answers but it is 
> certainly not good to have this kind of inconsistency.
> Also BTW: (type-of t) -> SYMBOL (MCL & LispWorks) but BOOLEAN (OpenMCL)
> Does this seem to be a problem in OpenMCL, or do you think the specifications 
> are too loose in this area?
> I'm not sure how best to approach the problem.  I might be able to kludge 
> something in the XML library, but it would sure be nice if the standard 
> dispatch mechanisms could handle this case properly.
> Any ideas would be greatly appreciated.
> Thanks,
> -Brent

More information about the Openmcl-devel mailing list