Emacs Lisp宏不会扩展列表

时间:2018-07-25 02:45:10

标签: emacs elisp-macro

这是我的宏,应该做的是用来自body的绑定将let包裹在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

错误可能有一些简单的解决方法,但我只是找不到它。

2 个答案:

答案 0 :(得分:3)

请记住,宏的参数是未经评估的 ,这意味着当您将my-vars-alist作为参数传递时,将逐字传递为 symbol { {1}}。

因此,在宏扩展期间,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的表格(或使用 M-x macroexpand-1)。

答案 1 :(得分:2)

我看起来您想做的就是将清单的键与其值绑定,因此您可以将这些键用作let主体中的变量。最近的Emacs中有一个内置的宏:

(let-alist '((a . 1) (b . 2))
  (message "a: %d, b: %d" .a .b))