[pro] The Best Examples of "Code is Data"

Scott L. Burson Scott at sympoiesis.com
Sun Sep 5 20:59:44 UTC 2010


On Sun, Sep 5, 2010 at 11:56 AM, Yakov Zaytsev <zaytsev.yakov at 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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mailman.common-lisp.net/pipermail/pro/attachments/20100905/53642388/attachment.html>


More information about the pro mailing list