首页 > 解决方案 > Emacs Lisp 宏不展开 Alist

问题描述

这是我的宏,它应该做的是用来自bodylet绑定包装一个vars-alist

(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

该错误可能有一些简单的解决方案,但我无法找到它。

标签: emacselisp-macro

解决方案


请记住,宏的参数是un-evaluated,这意味着当您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-alisteval,后者将其作为变量进行评估以获取 所需的列表mapcar


您可能还想引用您传递给macroexpand-1(或使用M-x pp-macroexpand-last-sexp)的表单。


推荐阅读