簡體   English   中英

如何將引用的sexp傳遞給宏

[英]how to pass quoted sexp to macro

我有一個函數可以替換列表中符號的所有實例:

(defun replace-symbol-in-sexp-fn (symbol-to-replace new-symbol sexp)
  (if (eq sexp nil)
      sexp
      (cons
       (if (listp (car sexp))
           (replace-symbol-in-sexp-fn symbol-to-replace new-symbol (car sexp))
           (if (eq (car sexp) symbol-to-replace)
               (setf (car sexp) new-symbol)
               (car sexp)))
       (replace-symbol-in-sexp-fn symbol-to-replace new-symbol (cdr sexp)))))

(defmacro replace-symbol-in-sexp (symbol-to-replace new-symbol sexp)
  `(replace-symbol-in-sexp-fn ,symbol-to-replace ,new-symbol ,sexp))

(macroexpand-1 (replace-symbol-in-sexp '+ '* (+ 2 3)))
; => TYPE-ERROR "The value 5 is not of type LIST" if sexp has comma,
; => UNBOUND-VARIABLE "The variable SEXP is unbound" if sexp has no comma

嘗試評估最終表達式時,我會遇到類型錯誤或未定義變量錯誤,具體取決於最后一行中的sexp是否逗號。 我已經測試過,如果給出,請替換symbol-in-sexp-fn,例如:

(replace-symbol-in-sexp-fn '+ '* '(+ 2 3)) ; => (* 2 3)

我現在正在嘗試使用宏來生成此文件,以便使sexp不必像'(+ 2 3)一樣被引用,因此我可以使用任意lisp代碼運行replace-symbol-in-sexp-fn。 顯然,我可以評估並傳遞引用為replace-symbol-in-sexp-fn的sexp,例如:

(eval (replace-symbol-in-sexp-fn '+ '* '(+ 2 3))

但這是模仿宏的笨拙嘗試,因此我寧願實際上僅使用宏。 有沒有一種干凈的方法可以處理宏? 我想念什么?

似乎您不想擴展到函數調用,而是使用該函數來擴展代碼。 那你不應該引用它:

(defmacro replace-symbol-in-sexp (symbol-to-replace new-symbol sexp)
  (replace-symbol-in-sexp-fn symbol-to-replace new-symbol sexp))

我的印象是,您只是在嘗試重新實現symbol-macroletsymbol-macrolet

因此,您重新實現了Common Lisp函數nsubst subst是普通版本, n表示它是破壞性版本(非約束)。

請注意,在便攜式Common Lisp中,修改文字數據不是一個好主意。 效果是不確定的。 暫時忽略一下:

(macroexpand-1 (replace-symbol-in-sexp '+ '* (+ 2 3)))

但是,您可能想宏擴展表達式而不是結果嗎? 可能應該是:

(macroexpand-1 '(replace-symbol-in-sexp '+ '* (+ 2 3)))

但是那個宏沒有意義。 生成的代碼為false,因為最后一個參數的值不等於列表。 宏必須創建有用的代碼。 如您所見,最后一個表達式未引用,這沒有任何意義。

CL-USER 14 > (macroexpand-1 '(replace-symbol-in-sexp '+ '* (+ 2 3)))
(REPLACE-SYMBOL-IN-SEXP-FN (QUOTE +) (QUOTE *) (+ 2 3))

讓我們介紹一個報價:

(defmacro replace-symbol-in-sexp (symbol-to-replace new-symbol sexp)
   `(replace-symbol-in-sexp-fn ,symbol-to-replace ,new-symbol ',sexp))

CL-USER 17 > (macroexpand-1 '(replace-symbol-in-sexp '+ '* (+ 2 3)))
(REPLACE-SYMBOL-IN-SEXP-FN (QUOTE +) (QUOTE *) (QUOTE (+ 2 3)))

該宏有用嗎? 我有疑問

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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