簡體   English   中英

常見的Lisp Lisp-1宏

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

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