On Mon, Dec 27, 2010 at 3:28 PM, Sam Steingold sds@gnu.org wrote:
On Mon, Dec 27, 2010 at 2:02 AM, Pascal Costanza pc@p-cos.net wrote:
On 27 Dec 2010, at 04:37, Sam Steingold wrote:
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?
Since a class may be redefined at runtime, you want to use the MOP at runtime anyway.
no, these classes will not change at run time (they are actually structs); and even if they will, I will be using deffoo for that.
If you are really sure that the class doesn't change at runtime,
I am.
you can alternatively wrap the defclass form into an (eval-when (:compile-toplevel :load-toplevel :execute) ...)
nope. my macro calls MOP functions at macroexpansion time, so this eval-when will not help me. I wonder if the deprecated #, will help me.
You could of course also decide to parse the slot definition forms yourself.
I am too lazy for that :-(
How about:
(defmacro deffoo (class slots) `(progn ,(let ((defclass-form `(defclass ,class () ,slots))) (eval defclass-form) defclass-form) (defun foo (x) ...)))
This will execute the defclass-form twice, if you compile and load the code containing the macro in the same session. So with structs it might not work if your implementation signals an error on struct redefinition (which IIRC it can do).
hth, Alessio