common-lispsbclclosccl

How to portably create a class at run-time in Common-Lisp CLOS


I need to create a class at run-time, possibly without resorting to eval. Knowing that the metaclass protocol is not fully standardized in Common-Lisp, after browsing through the The Common Lisp Object System MetaObject Protocol, I tried the following code to create a class, instantiate it, and set a slot value of the instance to a number:

(defparameter *my-class*
  (make-instance 'standard-class
                 :name 'my-class
                 :direct-slots '((:name x :readers (get-x) :writers ((setf get-x))))))

(defparameter *my-instance* (make-instance *my-class*))

(setf (get-x *my-instance*) 42) ;; => 42

Unfortunately this code works correctly on SBCL, but not on CCL, where the class creation seems to work, but the instance creation (make-instance *my-class*) causes the following error:

There is no applicable method for the generic function:
  #<STANDARD-GENERIC-FUNCTION INITIALIZE-INSTANCE #x30200002481F>
when called with arguments:
  (#<error printing CONS #x302001A9F6A3>
   [Condition of type CCL:NO-APPLICABLE-METHOD-EXISTS]

I tried looking at closer-mop package, that should hide the differences between the various implementations for the meta-object protocol, but I could not find any function or class useful to my scope.

So the question is: is there a portable way of creating a class and instantiating it at run time by using directly the metaclass level of CLOS?


Solution

  • CCL seems to require that you manually specify the direct superclasses as well.

    (defparameter *my-class*
      (make-instance 'standard-class
                     :name 'my-class
                     :direct-slots '((:name x :readers (get-x) :writers ((setf get-x))))
                     :direct-superclasses (list (find-class 'standard-object))))