【发布时间】:2016-06-25 17:36:31
【问题描述】:
我正在尝试编写一个宏,它采用变量列表和代码体,并确保在代码体执行后变量恢复到其原始值(Paul Graham 的 ANSI Common Lisp 中的练习 10.6)。
但是,我不清楚为什么我的 gensym 会按照我的预期在一个地方进行评估,而不是另一个类似的地方(注意:我知道有更好的解决方案。我只是想弄清楚为什么评估的差异)。
这是lst gensym 计算为传递给mapcar 的lambda 内的列表的第一个定义:
(defmacro exec-reset-vars-1 (vars body)
(let ((lst (gensym)))
`(let ((,lst ,(reduce #'(lambda (acc var) `(cons ,(symbol-value var) ,acc))
vars
:initial-value nil)))
,@body
,@(mapcar #'(lambda (var) `(setf ,var (car ,lst)))
vars))))
虽然它完全按照我的预期工作,但它不是练习的正确解决方案,因为我在尝试重置值时总是抓住lst 的第一个元素。我真的想映射超过 2 个列表。所以现在我写:
(defmacro exec-reset-vars-2 (vars body)
(let ((lst (gensym)))
`(let ((,lst ,(reduce #'(lambda (acc var) `(cons ,(symbol-value var) ,acc))
vars
:initial-value nil)))
,@body
,@(mapcar #'(lambda (var val) `(setf ,var ,val))
vars
lst))))
但现在我收到一条错误消息,提示 #:G3984 不是列表。如果我用(symbol-value lst) 替换它,我会收到一条错误消息,说变量没有价值。但为什么不呢?为什么它在lambda 中的setf 内有一个值,而不是作为传递给mapcar 的参数?
【问题讨论】:
标签: macros lisp common-lisp