On Sun, Sep 5, 2010 at 11:56 AM, Yakov Zaytsev <zaytsev.yakov@gmail.com> wrote:

(defmacro define-struct-getter (struct package &rest slots)
  (loop for s in slots
     do (let ((acc (intern (concatenate 'string (symbol-name struct) "-" (symbol-name s))))
                   (sp (intern s package)))
               (eval `(defmacro ,acc (object)
                        `(access-slot ,object ',',sp))))))
 

Rather than eval-ing the consed defmacro form at macroexpansion time, which doesn't do the right thing when a DEFINE-STRUCT-GETTER form is in a file being compiled, it would be better to do something like this:

(defmacro define-struct-getter (struct package &rest slots)
  `(progn
     ,@(mapcar (lambda (s)
         (let ((acc (intern (concatenate 'string (symbol-name struct) "-" (symbol-name s))))
               (sp (intern s package))
           `(defmacro ,acc (object)
              `(access-slot object ',',sp))))
           slots)))

As tempting as it is to call EVAL for various purposes, the reality is that correct uses of EVAL are quite rare.  In fact, unless you're writing your own read-eval-print loop of some kind, the best rule of thumb is that if you're calling EVAL explicitly, you've made a mistake.  I have trouble coming up with any exceptions to this rule other than a REPL.

Also, supplying a package to re-intern the slot names in, while not outright wrong, is an unusual kind of thing to do.  Is it that hard to just type the slot names with package prefixes?

All that said -- if you're using nested backquotes successfully, you're clearly starting to get the hang of macros.

-- Scott