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)))
我尝试在 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)))