代码之家  ›  专栏  ›  技术社区  ›  Dennis Ng

Lisp宏的基本思想

  •  0
  • Dennis Ng  · 技术社区  · 10 年前

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

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

    3 回复  |  直到 10 年前
        1
  •  2
  •   Rainer Joswig mmmmmm    10 年前
    (defmacro formatdm (stream string &rest allparm) ;;; later add (if ...
      (format stream string allparm))
    

    宏应该返回源代码,而不是执行。在这里,只有了解 allparm 处于宏扩展时间。它是源代码的一部分: (x) .

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

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

        2
  •  1
  •   tonso laalto    10 年前

    你的“函数一”的问题是你通过了 &rest 参数 format 按原样运行。传递 x formatdf 导致创建包含一个参数的列表,该参数绑定到 allparm . 因此,如果您只想打印第一个参数,您应该写:

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

    或修复 总体安排 在…内 格式df 以下一种方式:

    (apply #'format stream string allparm)
    
        3
  •  0
  •   Dennis Ng    10 年前

    (defparameter 节点错误 t)上 (套x 1) (格式t“x为~a”x);;;生成->x为1

    ;;; 要生成相同的版本并准备nodebug版本,需要执行以下操作:

    ;;; 使用defmacro

    (defmacro formatdmadv(流字符串&rest allparm) `(格式、流、字符串、@allparm))

    (formatdmadv t“formatdmadvx是~a”x);;;生成->x是1<--宏校正

    ;;; 或按建议使用defun

    (formatdf_car t“formatdf_carx是~a”x);;;生成->x是1<--趣味正确

    (defun formatdf(流字符串&rest allparm) (apply#'格式(list*流字符串allparm))

    (formatdf t“formatdf使用apply x是~a”x);;;生成->x是1<--趣味正确

    ;;; ---- 以下内容不正确

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

    (formatdf_err t“formatdf_err:x是~a”x);;;生成->x是(1)

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

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

    (formatdm t“formatdm x是~a”x);;;生成->x是(x)

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

    (pprint(macroexpand-1'(formatdm t“formatdm x是~a”x))

    (pprint(宏扩展'(formatdm t“formatdm x是~a”x))

    (pprint(macroexpand-1'(formatdm t“formatdm b”c)))

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

    (pprint(macroexpand-1'(formatdmadv t“formatdmadvx是~a”x))

    (pprint(宏扩展'(formatdmadv t“formatdmadvx是~a”x))

    (pprint(macroexpand-1'(formatdmadv t“formatdmadvb”c))