【问题标题】:macro: value is not of type LIST宏:值不是 LIST 类型
【发布时间】:2024-01-21 12:04:01
【问题描述】:

我正在尝试编写一个可以同时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 上编译该函数会产生一些警告和错误(“变量 LISTS 已定义但从未使用过——如何??”;以及“值 LISTS 不是 LIST 类型”)。此外,根据编译器,由于某种原因,"~&pause mouse button1;~%" 部分是“无法访问的代码”,并在编译时被删除。怎么会?

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

【问题讨论】:

    标签: macros lisp common-lisp sbcl


    【解决方案1】:

    所以,显然我完全错误地处理了这个问题。不需要为此使用宏,通过在表达式上运行 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;~%")))
    

    【讨论】: