下面是一个示例代码:
(defun my-test (&rest values)
(macrolet ((my-macro (v)
`(list ,@v)))
(print values)
(my-macro values)))
(my-test 1 2 3 4)
;; The goal is to obtain : (1 2 3 4).
当我执行最后一行时,它打印(1 2 3 4)
,然后函数失败。当我执行defun或试图执行最后一行时,我会收到以下警告/错误(resp.):
; in: DEFUN MY-TEST
; (MY-PACKAGE::MY-MACRO VALUES)
; ==>
; (LIST . VALUES)
;
; caught ERROR:
; (LIST . VALUES) is not a proper list.
;
; compilation unit finished
; caught 1 ERROR condition
为什么会失败?
一个宏转换代码,它不知道任何关于运行时值的信息,只知道文字代码。例如
(cond (p1 e1) (p2 e2) (t e3))
变成
(if p1
e1
(if p2
e3))
现在我们真的不知道p1
是什么。现在看看你的代码:
(defun my-test (&rest values)
(macrolet ((my-macro (v)
`(list ,@v)))
(print values)
(my-macro values)))
因此,在创建my-test
时会展开宏。你能告诉我my-macro
如果不是(list . values)
,将如何扩展(my-macro values)
吗?(list . values)
不是有效的Common Lisp,这就是您的错误来源。
您也许应该在没有宏的情况下执行此操作。只要使用values
就可以了。要调用以列表为参数的函数,可以使用apply
。要复制不需要的列表,可以使用copy-list
或copy-tree