Lisp宏的基本思想

时间:2015-03-11 14:48:39

标签: macros lisp common-lisp

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

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

3 个答案:

答案 0 :(得分:2)

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

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

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

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

答案 1 :(得分:1)

“功能一”的问题在于您将&rest参数原样传递给format功能。将x传递给formatdf会导致创建一个包含一个参数的列表,该列表绑定到allparm。 因此,如果您只想打印第一个参数,您应该写:

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

或以下一种方式在format内修复formatdf

(apply #'format stream string allparm)

答案 2 :(得分:0)

(defparameter nodebug t) (setf x 1) (格式t" x是~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< - fun correct

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

(formatdf t" formatdf using apply x is~a" x);;;生成 - > x是1< - fun correct

;;; ----以下是不正确的

(defun formatdf_err(stream string& rest allparm)(格式化流字符串allparm))

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

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

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

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

;;; -----测试确认结果

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

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

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

;;; ---错误的一个,甚至不生成源代码

(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)))