这是我的宏,它应该做的是用vars-alist
的绑定将body
包装在let
(defmacro with-vars-alist (vars-alist &rest body)
`(let (,@(mapcar (lambda (cell) (list (car cell) (cdr cell))) vars-alist))
,@body))
当我查看使用以下代码扩展的内容时
(defvar my-vars-alist '((var1 . "var1")
(var2 . "var2")))
(macroexpand-1 (with-vars-alist my-vars-alist `(concat ,var1 ,var2)))
我收到错误cons: Wrong type argument: sequencep, my-vars-alist
但是检查它(sequencep my-vars-alist)
返回t
。
错误可能是有一些简单的解决方案,但我只是找不到它。
请记住,宏的参数是未计算的,这意味着当您将my-vars-alist
作为参数传递时,它会作为符号my-vars-alist
逐字传递。
因此,在宏扩展期间,vars-alist
计算符号my-vars-alist
而不是列表((var1 . "var1") (var2 . "var2"))
。
因此,错误不是抱怨变量my-vars-alist
不包含序列作为其值,而是符号my-vars-alist
本身不是序列(这是正确的 - 它是一个符号)。
检查它
(sequencep my-vars-alist)
返回t
。
这也是正确的,因为my-vars-alist
被评估为其值的变量((var1 . "var1") (var2 . "var2"))
所以你需要eval
这个论点,例如:
,@(mapcar (lambda (cell) (list (car cell) (cdr cell)))
(eval vars-alist))
由于vars-alist
已经被评估为符号my-vars-alist
,此更改意味着我们将该符号my-vars-alist
传递给eval
,将其评估为变量以获取mapcar
所需的列表。
您可能还想引用传递给macroexpand-1
的表单(或使用M-xpp-macroexpand-last-sexp
)。
看起来您要做的是将 alist 的键绑定到它们的值,这样您就可以将这些键用作 let 正文中的变量。 在最近的 Emacs 中有一个内置的宏:
(let-alist '((a . 1) (b . 2))
(message "a: %d, b: %d" .a .b))