[英]Saving symbol-names of argument in macro
Paul Grahams ANSI Common Lisp本書中的一項練習是:定義一個宏,該宏接受變量列表和代碼主體,並確保在評估代碼主體后將變量還原為其原始值。
我在本練習中遇到的問題是如何保存輸入變量的符號名稱。 在下面的內容中,我僅保存了符號綁定到的值。
(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的提示)。 但是像Vatine的答案那樣對變量進行陰影處理可能更優雅。
(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)))
我懷疑這在最終定義中不會有用。 在運行時,符號列表無濟於事。 而是尋找一個在宏擴展中插入列表的好地方。
另外,您可能要使用GENSYM
而不是硬編碼的變量名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))
我真的很喜歡Vatine的方法。 這是一個擴展為相同代碼的實現,但是使用mapcar而不是loop宏:
(defmacro save-run (varlist &body body)
`(let ,(mapcar #'list varlist varlist)
,@body))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.