簡體   English   中英

將參數的符號名稱保存在宏中

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM