Macros 在宏中保存参数的符号名称
Paul Grahams ANSI Common Lisp书中的一个练习是:定义一个宏,该宏接受一个变量列表和一个代码体,并确保在对代码体求值后变量恢复为其原始值 我在这个练习中遇到的问题是如何保存输入变量的符号名。下面我有一个开始,我只保存符号绑定到的值Macros 在宏中保存参数的符号名称,macros,common-lisp,Macros,Common Lisp,Paul Grahams ANSI Common Lisp书中的一个练习是:定义一个宏,该宏接受一个变量列表和一个代码体,并确保在对代码体求值后变量恢复为其原始值 我在这个练习中遇到的问题是如何保存输入变量的符号名。下面我有一个开始,我只保存符号绑定到的值 (defmacro save-run (varlist &body body) `(let ((valuelist (list ,@varlist))) (format t "valuelist: ~A" valuelis
(defmacro save-run (varlist &body body)
`(let ((valuelist (list ,@varlist)))
(format t "valuelist: ~A" valuelist)))
(let ((a 5)(b 6))
(values '(a b))
(save-run (a b)
(setf a 7)
(setf b 8)))
[507]> valuelist: (5 6)
编辑:这里有一个解决方案,保存变量,然后还原(使用下面finnw的提示)。但在梵蒂娜的回答中隐藏变量可能更优雅
(defmacro save-run (varlist &body body)
`(let ((valuelist (list ,@varlist)))
,@body
(multiple-value-setq ,varlist (values-list valuelist))))
要获取符号列表,只需引用
VARLIST
的内容即可:
(defmacro save-run (varlist &body body)
`(let ((namelist ',varlist)
(valuelist (list ,@varlist)))
(format t "namelist: ~A~%" namelist)
(format t "valuelist: ~A~%" valuelist)))
(defmacro save-run (varlist &body body)
(let ((valuelist (gensym)))
`(let ((,valuelist (list ,@varlist)))
,@body
(setf (values ,@varlist) (values-list ,valuelist)))))
然而,我怀疑这在最终定义中不会有用。在运行时,您无法对符号列表进行太多处理。相反,请在宏展开中寻找插入列表的好位置
此外,您可能希望使用GENSYM
而不是硬编码变量名VALUELIST
:
(defmacro save-run (varlist &body body)
`(let ((namelist ',varlist)
(valuelist (list ,@varlist)))
(format t "namelist: ~A~%" namelist)
(format t "valuelist: ~A~%" valuelist)))
(defmacro save-run (varlist &body body)
(let ((valuelist (gensym)))
`(let ((,valuelist (list ,@varlist)))
,@body
(setf (values ,@varlist) (values-list ,valuelist)))))
就我个人而言,我会为我们想要保存的变量引入另一个绑定层 您在
varlist
中有一个变量列表,因此类似的方法可能会起作用:
(defmacro save-run (varlist &body body)
`(let ,(loop for var in varlist
collect (list var var))
,@body))
我真的很喜欢梵蒂娜的方法。下面是一个扩展为相同代码的实现,但使用mapcar而不是loop宏:
(defmacro save-run (varlist &body body)
`(let ,(mapcar #'list varlist varlist)
,@body))
很好,我不知道你可以这样组合引号和逗号。对不起,我应该说不要使用名称列表,你需要值列表。我的错。我喜欢它,比保存和恢复更优雅。你不需要
(progn,@body)
。只要,@body
也会有同样的效果。如果您使用(setf(values,@varlist)…)
而不是(multiple value setq,varlist…)
那么一些变量可以是符号以外的位置,例如(save run((cdr x))…)
不确定您在这里的意思。我查看了文档,setf只能接受偶数个成对分配的参数,而不是列表。