如何在宏的帮助下 defconst 一堆东西?

How to defconst a bunch of stuff with the help of a macro?

我必须在我的程序中 defconst 64 个值,鉴于 Lisp 具有我从未使用过的著名宏工具,我认为这是我的机会。但是它似乎并没有像我预期的那样工作...


(defun square-name (square-index)
  (multiple-value-bind (row col) (floor square-index 8)
    (format nil "SQ-~A~D"
            (string (code-char (+ (char-code #\A) col)))
            (+ 1 row))))

(defmacro defconst-all-square-names ()
  (dotimes (i 64)
    `(defconstant ,(make-symbol (square-name i)) ,i)))
    
(defconst-all-square-names)

鉴于我对 lisp 和宏比较陌生,有人可以解释一下吗,

也许我只是错过了一些宣言或类似的东西。上面的代码在没有警告或错误的情况下编译,并且在加载它之后(为此使用 emacs、slime 和 CTRL-C-K),定义了 none 个常量。

更新

在与@Rainer Joswig 聊了聊之后(非常感谢!)结果是, 那

综上所述,工作代码现在如下所示:

(defun square-name (square-index)
  (multiple-value-bind (row col) (floor square-index 8)
    (format nil "SQ-~A~D" (string (code-char (+ (char-code #\A) col))) (+ 1 row))))

(defmacro defconst-all-square-names ()
  (append '(progn)
      (loop for i from 0 to 63 collect
           `(defconstant ,(intern (square-name i)) ,i))))
    
(defconst-all-square-names)

我们来看看dotimes:

* (dotimes (i 10) 42)
NIL

return上面的dotimes形式NIL,同()->空列表。基本上return没什么。

所以你的宏 return 什么都没有。因此代码 (defconst-all-square-names) 扩展为 ()。使用 macroexpand-1.

检查

总结一下:

  • 你的宏没有side-effect
  • 您的宏扩展为一个空列表,因为您的宏 returns ()

您需要修复后者。

记住:宏的第一个目的是生成代码。 -> 你需要生成代码,否则你需要输入。由于您的宏 return () 和 运行 () 自然不会产生任何影响 -> 什么都没有发生。