Quazi-quote, missing one evaluation

Discussion of Common Lisp
Post Reply
wvxvw
Posts: 127
Joined: Sat Mar 26, 2011 6:23 am

Quazi-quote, missing one evaluation

Post by wvxvw » Tue Oct 02, 2012 1:24 am

Hi. I'm trying to come up with a simple table to object mapping (a learning exercise for now, not a real thing). Below is my code, where I can achieve what I need, but in a clumsy way:

Code: Select all

(defclass db-object () ())

(defun slot-list-from-query (query)
  (format t "slot-list-from-query: ~s~&" query)
  (mapcar
   #'(lambda (pair)
       (format t "pair: ~s~&" pair)
       (let ((name (string-upcase (symbol-name (car pair)))))
         (list (intern name)
               :accessor
               (intern (concatenate 'string name "-OF"))
               :initarg (intern name "KEYWORD")))) query))

(defun make-class-with-slots (name slots)
  (format t "defining class: ~s, slots: ~s~&" name slots)
  `(defclass ,name (db-object) ,slots))

(defmacro table-to-class (name describe-table-query)
  `(let ((db-class (make-class-with-slots
                    ',name
                    (slot-list-from-query ,describe-table-query))))
     (eval db-class) ; this line particularly bothers me.
     (defmethod initialize-instance :after ((object ,name) &key raw-data)
                (mapcar
                 #'(lambda (pair)
                     (setf (slot-value object
                                       (find-symbol
                                        (string-upcase
                                         (symbol-name (car pair)))))
                           (cdr pair))) raw-data))
     db-class))
There are too many macros inside macrose, and I can't think of a way to make it work better. I need to evaluate a macro which is dynamically constructed inside another macro, and that just too many nesting levels then I can handle :cry:

I've also duplicated the code here http://pastebin.com/iXXMCDad for better readability.

pjstirling
Posts: 166
Joined: Sun Nov 28, 2010 4:21 pm

Re: Quazi-quote, missing one evaluation

Post by pjstirling » Tue Oct 02, 2012 5:34 am

You've managed to avoid the double quasi-quote pit-trap with your helper, all you need do is use it :)

Code: Select all

(defclass db-object () ())
     
(eval-when (:compile-toplevel :load-toplevel :execute)
  (defun slot-list-from-query (query)
    (format t "slot-list-from-query: ~s~&" query)
    (mapcar
     #'(lambda (pair)
	 (format t "pair: ~s~&" pair)
	 (let ((name (string-upcase (symbol-name (car pair)))))
	   (list (intern name)
		 :accessor
		 (intern (concatenate 'string name "-OF"))
		 :initarg (intern name "KEYWORD")))) query))

  (defun make-class-with-slots (name slots)
    (format t "defining class: ~s, slots: ~s~&" name slots)
    `(defclass ,name (db-object) ,slots)))

(defmacro table-to-class (name describe-table-query)
  `(progn
     ,(make-class-with-slots name
			     (slot-list-from-query describe-table-query))
     (defmethod initialize-instance :after ((object ,name) &key raw-data)
       (mapcar
	#'(lambda (pair)
	    (setf (slot-value object
			      (find-symbol
			       (string-upcase
				(symbol-name (car pair)))))
		  (cdr pair))) raw-data))
     db-class))



wvxvw
Posts: 127
Joined: Sat Mar 26, 2011 6:23 am

Re: Quazi-quote, missing one evaluation

Post by wvxvw » Thu Nov 01, 2012 1:41 pm

Oh, sorry, I've totally missed this reply! Although, too late, thanks!

Post Reply