macroscommon-lispbackquote

Why this Common Lisp macro does not work? Is the answer sheet from the book wrong?


I am trying to learn Common Lisp with the book Common Lisp: A gentle introduction to Symbolic Computation. In addition, I am using SBCL, Emacs, and Slime.

In chapter 14, the last one, the author covers macros. The following problem is presented:

Write a macro called VARIABLE-CHAIN that accepts any number of inputs. The expression (VARIABLE-CHAIN A B C D) should expand into an expression that sets A to ’B, B to ’C, and C to ’D.

The answer sheet is:

enter image description here

Copying from the pdf and pasting it here:

(defmacro variable-chain (&rest vars)
 ‘(progn 
    ,@(do ((v vars (rest v))
           (res nil))
          ((null (rest v)) (reverse res))
        (push ‘(setf ,(first v) ’,(second v))
               res))))

In Emacs, I used this hack to remove smart-quotes. Pasting it in Emacs, I get:

(defmacro variable-chain (&rest vars)
  '(progn
     ,@(do ((v vars (rest v))
            (res nil))
           ((null (rest v)) (reverse res))
         (push '(setf ,(first v)
                      ',(second v))
                res))))

Unfortunately, I cannot compile it to the Slime's REPL, it throws an error:

> READ error during COMPILE-FILE: Comma not inside a backquote.

I tried changing '(progn to:

`(progn

But it also did not work: "comma not inside a backquote".

Did I do something wrong? Or, is the answer sheet incorrect?

Thanks.


Solution

  • You need to change the other one as well:

    (defmacro variable-chain (&rest vars)
      `(progn
     ;; this one you did change
         ,@(do ((v vars (rest v))
                (res nil))
               ((null (rest v)) (reverse res))
             (push `(setf ,(first v)
               ;; ^^^ also need to change this one
                          ',(second v))
                    res))))
    

    The is the backquote, whereas is the regular quote, but your "hack" turned both of them into the regular quote ' chars erroneously:

    (defmacro variable-chain (&rest vars)
     ‘(progn 
     ;; backquote
        ,@(do ((v vars (rest v))
               (res nil))
              ((null (rest v)) (reverse res))
            (push ‘(setf ,(first v) ’,(second v))
              ;; backquote         quote
                   res))))