[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Runtime Defclass (was: Compiler Excised)

Skip Egdorf <hwe@lanl.gov> writes:
> 2. Use (eval '(defclass ...)) because nobody has agreed on the part
> of the metaobject protocol for portable runtime class creation. Is
> it ensure-class? Perhaps it is (make-instance 'standard-class)? 
> Perhaps its... This could be fixed by the vendors. Unfortunatly it
> takes agreement on just whose mechanism to use. So we can lump it
> in with our dreams for a standard defsys and FFI. ... And a few
> more turn to C++ and Visual Basic...

Ensure-class might be the way to go but it's probably overkill and
MCL doesn't support it anyway. And much of the work of ensure-class
is involved in 
a) The distinction between making a new class vs. 
   redefining an old one, and the consequent lazy update of all
   its instances that's needed, and
b) Dealing with the case where all the superclasses aren't defined yet.

I suspect that in many applications requiring runtime class creation,
the system can be engineered so that neither of these cases occurs.

When those cases do not occur, I have used a function similar to the
following with good results in MCL. The starting point for this was AMOP,
page 69, but I've modified it slightly to take an explicit name argument: 

(defun make-programmatic-class (name superclass-list 
                                    &key (metaclass 'standard-class)
                                    (slots nil))
      (let ((newclass
             (make-instance metaclass ;   all the superclasses
            :name name
            :direct-superclasses superclass-list
            :direct-slots (when slots
                            (cons nil slots))) ; I don't know why
             ;           I have to cons nil here, but I do in MCL
            (setf (find-class name) newclass) ; Make sure find-class can
                                              ; find it
#| Example:
(defclass goo () ())
(defclass foo () ())
(make-programmatic-class 'newclass
                          (list (find-class 'goo)
                               (find-class 'foo))
                         '((new-SLOT1 ("initform1") (:initarg1))
                           (new-slot2 ("intiform2") (:initarg2))))

This will not create accessor methods on the slots. If you need these,
macroexpand a defclass form to see how it's done.

Dealing with undefined superclasses and redefining programmatic
classes in a transportable way is left as an exercise for the reader.

Shannon Spires
Internet: svspire@sandia.gov
Voice: 505-844-4287
Fax: 505-844-3296