宏:值不是 LIST 类型

macro: value is not of type LIST

我正在尝试编写一个可以同时 eazygnuplot:plot 许多系列的宏。理想情况下,我想写类似 (plotlists lists) 的内容,其中 lists 看起来像这样:

'(((57 91)) ((83 1) (90 8) (78 18)) ((42 19)))

也就是说,listsk 对列表的列表(更具体地说,这是在使用 k-means 聚类后平面上的点列表)。我提到的宏应该扩展成类似的东西:

(eazy-gnuplot:plot (lambda ()
                     (dolist (p l1)
                       (format t "~&~A ~A" (first p) (second p)))))
(eazy-gnuplot:plot (lambda ()
                     (dolist (p l2)
                       (format t "~&~A ~A" (first p) (second p)))))

...等等。我的想法是写这样的东西:

(defmacro plotlists (lists)
  `(progn ,@(mapcar #'(lambda (ll)
                        '(eazy-gnuplot:plot
                             (lambda ()
                                (dolist (p ll)
                                  (format t "~&~A ~A" (first p) (second p))))))
                    lists)))

该宏由函数 scatter 调用,如下所示:

(defun scatter (lists)
  (eazy-gnuplot:with-plots (*standard-output* :debug t)
    (eazy-gnuplot:gp-setup :terminal '(:qt))
    (plotlists lists)
    (format t "~&pause mouse button1;~%")))

但是,在 SBCL 上编译该函数会出现一些警告和错误("the variable LISTS is defined but never used -- how??";和 "the value LISTS is not of type LIST")。此外,根据编译器的说法,由于某种原因,"~&pause mouse button1;~%" 部分是 "unreachable code" 并在编译时被删除。怎么会?

我对 Lisp 知之甚少,但这让我很困惑。有人对此有任何想法吗?

所以,显然我完全错误地处理了这个问题。没有必要为此使用宏,正如表达式中的 运行 MACROEXPAND-1 所表明的那样。 LISTS 的值不是 LIST 类型,因为它只是一个 SYMBOL,这是宏展开时唯一可用的。我只是用另一个 DOLIST:

替换了宏
(defun scatter (lists)
  (eazy-gnuplot:with-plots (*standard-output* :debug t)
    (eazy-gnuplot:gp-setup :terminal '(:qt))
    (dolist (cluster lists)
      (eazy-gnuplot:plot (lambda ()
                           (dolist (point cluster)
                             (format t "~&~A ~A" (first point) (second point))))))
    (format t "~&pause mouse button1;~%")))