Patrick (patrickwonders) wrote,
Patrick
patrickwonders

How I Know I Don't Know Enough About Lisp Macros

Last night, I posted a long article on my website about How I Know I Don't Know Enough About Lisp Macros. For those who are unfamiliar with Lisp macros, you might enjoy reading the article. I spend a good deal of setup time talking about how Lisp macros kick the pants off of anything else you've heard called a macro before. For here, I will just excerpt the relevant bits for those already familiar with Lisp macros in hopes that you might give me guidance.

In the article, the main example that I work with is assuming that you want to think about your code in terms of jump tables, but you don't necessarily want to write a separate function for each item in the table. You might write some macro like this:

(defmacro do-jump-table ( choice &rest options )
  `(case ,choice
     ,@(loop for ii from 0
            for oo in options
            collecting (list ii oo))
     (otherwise (do-something-graceful))))

Then, you could use it something like this:

(do-jump-table op-code
               (write "NOOP")
               (write "SYNC")
               (when (>= +protocol-version+ 1)
                 (write "QUIT")))

Which would expand to:

(case op-code
  (0 (write "NOOP"))
  (1 (write "SYNC"))
  (2 (when (>= +protocol-version+ 1)
       (write "QUIT")))
  (otherwise (do-something-graceful)))

The do-jump-table macro we just defined expands to one statement (one lisp form): (CASE ...). There are many times when I want my macro to expand to more than one form, however. This isn't legit. I still end up wanting to do it. For example, I might think that since I'm doing things with macros, that I might want the whole (CASE ...) construct to be in the main code and just have the macro expand the different cases:

(case op-code
    (do-jump-table-cases (write "NOOP")
                         (write "SYNC")
                         (when (>= +protocol-version+ 1)
                             (write "QUIT")))
    (otherwise (do-something-especially-graceful)))

Lisp says no. I can understand why it says that. In this case, it's easy enough to work around. But, in other cases, I end up flailing.

I feel that once I understand Lisp macros more completely, I won't keep trying to jam that gorgeous, round peg into all of these square holes in my logic. Anyone have any guidance here?

Tags: lisp
Subscribe
  • Post a new comment

    Error

    default userpic

    Your reply will be screened

    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.
  • 14 comments