[英]Common Lisp Lisp-1 macro
我正在嘗試模擬通用lisp中方案的單個名稱空間,並使用一個宏(基於Doug Hoyte的宏)擴展為lambda,其中每次使用f!
函數位置中的符號(類似於Doug Hoyte的o!
和g!
符號)擴展為相同的表達式,但是在每次調用的函數位置中添加了funcall
。 例如:
(fplambda (f!z x) (f!z x x))
將擴展為:
(LAMBDA (F!Z X) (FUNCALL F!Z X X))
該宏當前如下所示:
(defmacro fplambda (parms &body body)
(let ((syms (remove-duplicates
(remove-if-not #'f!-symbol-p
(flatten body)))))
`(lambda ,parms
(macrolet ,(mapcar
(lambda (f)
`(,f (&rest parmlist) `(funcall ,',f ',@parmlist)))
syms))
,@body)))
但鑒於上述輸入,它擴展了(據我所知):
(LAMBDA (F!F X)
(MACROLET ((F!F (&REST PARMLIST) `(FUNCALL ,'F!F ',@PARMLIST))))
(F!F X X))
在宏定義中,不應用F!F引用或不使用引號,而使用parmlist則應僅使用不引用。 到底是怎么回事? 提前致謝!
您的定義基本上是正確的。 您剛剛犯了兩個非常簡單的錯誤。 第一個是不匹配的括號。 宏不包括主體(在輸出中,宏和主體處於相同的縮進級別)。
至於嵌套的反引號,唯一的錯誤是parmlist之前的引號。 除此之外,其他一切都是正確的。 F!F前面的逗號和引號實際上是正確的。 來自hyperspec :“實現可以自由地將帶反引號的形式F1解釋為任何形式F2,在對其進行評估時,將產生與上述定義所暗示的結果相同的結果”。 由於內部反引號尚未擴展,因此它不必沒有引號和反引號。 表達式`(,'x)實際上與`(x)相同。
嵌套的反引號非常復雜。 理解它們最簡單的方法就是閱讀斯蒂爾對它們的解釋 。
編輯:
關於是否可以在函數位置使用fplambda表達式的問題的答案為否。 從hyperspec的代碼評估部分 :“如果復合形式的car不是符號,則該汽車必須是lambda表達式,在這種情況下,復合形式是lambda形式。” 由於形式為(fplambda ...)的汽車不是lambda表達式,因此您的代碼不再是有效的Common Lisp代碼。
我發現有一個解決方法,但這有點丑陋。 您可以定義一個讀取器宏 ,使您可以編寫類似[[fplambda ...] ...)的內容並將其讀取為
((LAMBDA (&REST #:G1030) (APPLY (FPLAMBDA ...) #:G1030)) ...)
這會做你想要的。 這是允許您執行此操作的代碼:
(set-macro-character #\[ 'bracket-reader)
(set-macro-character #\] (get-macro-character #\)))
(defun bracket-reader (stream char)
"Read in a bracket."
(declare (ignore char))
(let ((gargs (gensym)))
`(lambda (&rest ,gargs)
(apply ,(read-delimited-list #\] stream t)
,gargs))))
我能想到的唯一其他解決方案是使用某種代碼遍歷器(我在那里幫不了你)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.