Q: Calling macro inside LOOP with list parameter.
Posted: Tue Jul 27, 2010 7:01 am
Hi All,
I'm experiencing a problem with a macro that takes a list as one of its parameters when it's called inside a LOOP. There is obviously some cloudy thinking on my part about how macro parameters are handled, but I am having a hard time spotting where I am going wrong. A contrived example that shows my problem is given below. The macro works fine when I call it directly, but when pulling the parameters from a structured list in a LOOP, it fails to do what I expected. Trying to macroexpand it out (even in the loop) isn't showing me the issue (thought it might be right in front of me.) Any guidance is appreciated.
Thanks,
Sean
I'm experiencing a problem with a macro that takes a list as one of its parameters when it's called inside a LOOP. There is obviously some cloudy thinking on my part about how macro parameters are handled, but I am having a hard time spotting where I am going wrong. A contrived example that shows my problem is given below. The macro works fine when I call it directly, but when pulling the parameters from a structured list in a LOOP, it fails to do what I expected. Trying to macroexpand it out (even in the loop) isn't showing me the issue (thought it might be right in front of me.) Any guidance is appreciated.
Thanks,
Sean
Code: Select all
;;; The code below shows a problem I'm having when trying to invoke a macro
;;; that accepts a list as one of the parameters while inside a LOOP.
;; Here is a sample macro. It generates a class and associated stream-formatter
;; based on the NAME and SLOT-LIST parameters.
(defmacro create-class-and-printer (class slot-list)
`(progn
(defclass ,class ()
,(loop for (slot value) in slot-list
collect (list slot :initform (string value))))
(defmethod print-object ((obj ,class) stream)
(format stream "~{~a ~}" (loop for (slot nil) in 'slot-list
collect (slot-value obj slot))))))
;; If I invoke the macro directly, it works just fine.
(create-class-and-printer spanish-dictionary ((one uno) (two dos) (three tres)))
;; But if I try to invoke the macro while iterating through a list, it appears
;; to have trouble with the slot-list parameter, and doesn't recognize it as a
;; LIST, but printing the type shows it as a CONS.
(let ((language-list '((spanish-dictionary ((one uno) (two dos) (three tres)))
(french-dictionary ((one un) (two deux) (three trois)))
(german-dictionary ((one ein) (two zwei) (three drei)))
(japanese-dictionary ((one ichi) (two ni) (three san))))))
(loop for (language dictionary) in language-list
do (format t "Dictionary is type: ~a~%" (type-of dictionary))
do (format t "Value of Dictionary is: ~a~%" dictionary)
do (format t "Is this a list? ~a~%" (listp dictionary))
do (create-class-and-printer language dictionary)))
;; I think this might have something to do with macro parameters being
;; "destructured" but am not clear on how to resolve it. My google searches
;; haven't turned up much, which either means I'm doing something extremely
;; dumb, extremely rare, or a combination of the two.