Lisp宏的基本思想

Basic idea of Lisp Macro

我尝试在 Lisp 中做一件非常简单的事情 - 找到一种方法来打开一个全局有价值的 nodebug t 然后一些调试格式的形式就会沉默。为此,我发现我无法理解以下内容的区别:

(defparameter *nodebug* t)
(setf x 1)

;;; the basic function 

(format t "x is ~a" x) ;;; generate -> x is 1


;;; try to use function not macro

(defun formatdf (stream string &rest allparm) ;;; later add (if ...
(format stream string allparm))

(formatdf t "x is ~a" x)  ;;; generate -> x is (1)


;;; try to use macro

(defmacro formatdm (stream string &rest allparm) ;;; later add (if ...
(format stream string allparm))

(formatdm t "x is ~a" x)  ;;; generate -> x is (X)

生成的代码(或函数)似乎与原始格式不一样。我的下一步应该做什么?

您的 "function one" 的问题是您将 &rest 参数按原样传递给 format 函数。将 x 传递给 formatdf 会导致创建一个包含一个参数的列表,该参数绑定到 allparm。 所以如果你只想打印第一个参数你应该写:

 (formatdf t "x is ~a" (car x))

或用下一种方式在 formatdf 中修复 format

(apply #'format stream string allparm)
(defmacro formatdm (stream string &rest allparm) ;;; later add (if ...
  (format stream string allparm))

宏应该 return 源代码,而不是执行。这里只有在宏扩展时查看 allparm 的值才有用。它是源代码的一部分:(x).

您需要 return 包含必要说明的列表 - 这里是调用格式的代码。

这是一本关于 Lisp 的很好的书,应该也解释了宏的基础知识:http://www.cs.cmu.edu/~dst/LispBook/

(defparameter nodebug t) (setf x 1) (格式 t "x is ~a" x);;;生成 -> x 为 1

;;;要生成相同的版本并为 nodebug 版本做准备,需要以下内容:

;;;使用 defmacro

(defmacro formatdmadv (stream string &rest allparm) `(格式,流,字符串,@allparm))

(formatdmadv t "formatdmadv x is ~a" x) ;;;生成 -> x 为 1 <-- 宏正确

;;;或按照建议使用 defun

(formatdf_car t "formatdf_car x is ~a" x) ;;;生成 -> x 是 1 <-- 有趣正确

(defun formatdf (stream string &rest allparm) (应用#'format (list* stream string allparm)))

(formatdf t "formatdf using apply x is ~a" x) ;;;生成 -> x 是 1 <-- 有趣正确

;;; ---- 以下不正确

(defun formatdf_err (stream string &rest allparm) (format stream string allparm))

(formatdf_err t "formatdf_err: x is ~a" x) ;;;生成 -> x 是 (1)

(defun formatdf_car (流字符串 &rest allparm) (格式化流字符串 (car allparm)))

(defmacro formatdm (stream string &rest allparm) (格式化流字符串 allparm))

(formatdm t "formatdm x is ~a" x) ;;;生成 -> x 是 (X)

;;; ----- 验证结果的测试

(pprint (macroexpand-1 '(formatdm t "formatdm x is ~a" x)))

(pprint (macroexpand '(formatdm t "formatdm x is ~a" x)))

(pprint (macroexpand-1 '(formatdm t "formatdm b" c)))

;;; --- 不正确,甚至不生成源代码 even

(pprint (macroexpand-1 '(formatdmadv t "formatdmadv x is ~a" x)))

(pprint (macroexpand '(formatdmadv t "formatdmadv x is ~a" x)))

(pprint (macroexpand-1 '(formatdmadv t "formatdmadv b" c)))