[pro] macros expanding to defclass + some mop code

Pascal Costanza pc at p-cos.net
Wed Dec 29 20:37:44 UTC 2010


On 27 Dec 2010, at 04:37, Sam Steingold wrote:

> Hi,
> I want to write a macro which would expand to a defclass + some code
> which uses the resulting class object using mop.
> e.g. (untested),
> (defmacro deffoo (class slots)
>  `(progn
>     (defclass ,class () ,slots)
>     (defun foo (x)
>       (list
>         ,@(mapcar (lambda (ds)
>                     `(,(car (slot-definition-readers ds)) x))
>                   (class-direct-slots (find-class class)))))))
> 
> which should expand
> (deffoo bar ((a :reader bar-a) (b :reader bar-b)))
> to something like this:
> (progn
>  (defclass bar () ((a :reader bar-a) (b :reader bar-b)))
>  (defun foo (x) (list (bar-a x) (bar-b x))))
> 
> Alas, CLASS is not defined at read time when
>                (class-direct-slots (find-class class))
> and
>                (slot-definition-readers ds)
> want to be evaluated.
> 
> So, how do I do this?


Just to be complete, I insist that the 'right' way to do this is to do this at runtime. Here is a sketch of how to do this in such a way that you don't suffer that much from additional runtime overheads:

(defclass foo-dependent () ((function-symbol :initarg :function-symbol))

(defmethod update-dependent 
           ((class standard-class) (dependent foo-dependent) &rest initargs)
  (declare (ignore initargs))
  (setf (symbol-function (slot-value dependent 'function-symbol))
        (compile nil `(lambda (x)
                        (list 
                         ,@(loop for slot in (class-direct-slots class)
                                 for name = (slot-definition-name slot)
                                 collect `(slot-value x ',name)))))))

(defmacro deffoo (class slots)
  `(progn
     (defclass ,class () ,slots)
     (defun foo (x))
     (add-dependent (find-class ',class) (make-instance 'foo-dependent :function-symbol 'foo))
     (reinitialize-instance (find-class ',class))
     ',class))

[Untested.]

Other variations are possible, like using a method on finalize-inheritance instead of update-dependent, if you can afford to have a separate metaclass for this. If you are sure that the class doesn't change at runtime, you can still generate the body of the foo function at loadtime / runtime, after the complete class exists.

Of course, this adds to some amount of load-time overhead, which may not be acceptable under certain circumstances.

Pascal

-- 
Pascal Costanza, mailto:pc at p-cos.net, http://p-cos.net
Vrije Universiteit Brussel
Software Languages Lab
Pleinlaan 2, B-1050 Brussel, Belgium










More information about the pro mailing list