如何借助宏来解构一堆东西?

问题描述

我必须在程序中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,slim和CTRL-C-K进行了编译),均未定义任何常量。

更新

在与@Rainer Joswig聊天后(非常感谢!), 那

  • 宏必须返回一个要执行的代码
  • 我的(make-symbol...)构造并没有达到预期的效果,我不得不使用(intern...)

所有这些之后,工作代码现在看起来像这样:

(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

上面的dotimes表单返回NIL,与()->空列表相同。基本上它什么也不返回。

因此您的宏不返回任何内容。因此,代码(defconst-all-square-names)扩展为()。用macroexpand-1进行检查。

总结:

  • 您的宏没有副作用
  • 您的宏扩展为一个空列表,因为您的宏返回()

您需要修复后者。

请记住:宏的首要目的是生成代码。 ->您需要生成代码,否则需要键入。由于您的宏确实返回了(),并且运行()自然不会产生任何效果->仍然没有任何反应。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...