当前位置:  开发笔记 > 编程语言 > 正文

Lisp单元测试宏约定和最佳实践

如何解决《Lisp单元测试宏约定和最佳实践》经验,为你挑选了1个好方法。

我发现很难推断宏观扩张,并且想知道测试它们的最佳实践是什么.

所以如果我有一个宏,我可以通过执行一个级别的宏扩展macroexpand-1.

(defmacro incf-twice (n)
  `(progn
     (incf ,n)
     (incf ,n)))

例如

(macroexpand-1 '(incf-twice n))

评估为

(PROGN (INCF N) (INCF N))

将它变成对宏的测试似乎很简单.

(equalp (macroexpand-1 '(incf-twice n))
  '(progn (incf n) (incf n)))

是否有用于组织宏测试的既定惯例?还有,是否有一个库来总结s表达式之间的差异?



1> Rainer Joswi..:

通常,测试宏不是Lisp和Common Lisp的强大部分之一.Common Lisp(和Lisp方言一般)使用过程宏.宏可以依赖于运行时上下文,编译时上下文,实现等.它们也可能有副作用(比如在编译时环境中注册事物,在开发环境中注册事物等等).

所以有人可能想测试一下:

生成正确的代码

生成的代码实际上做了正确的事情

生成的代码实际上在代码上下文中有效

在复杂的宏的情况下,宏参数实际上是正确解析的.想想loop,defstruct...宏.

宏检测到错误形成的参数代码.再次,想想宏loopdefstruct.

副作用

从上面的列表可以推断,在开发宏时最好最小化所有这些问题区域.但是:那里真的有非常复杂的宏.真可怕的.特别是那些习惯于实现新域特定语言的人.

使用equalp比较代码之类的东西仅适用于相对简单的宏.宏通常会引入新的,未加工的和唯一的符号.因此equalp将无法与那些人合作.

示例:(rotatef a b)看起来很简单,但扩展实际上很复杂:

CL-USER 28 > (pprint (macroexpand-1 '(rotatef a b)))

(PROGN
  (LET* ()
    (LET ((#:|Store-Var-1234| A))
      (LET* ()
        (LET ((#:|Store-Var-1233| B))
          (PROGN
            (SETQ A #:|Store-Var-1233|)
            (SETQ B #:|Store-Var-1234|))))))
  NIL)

#:|Store-Var-1233| 是一个符号,它是未处理的并由宏新创建的.

另一个具有复杂扩展的简单宏形式将是(defstruct s b).

因此,需要一个s表达式模式匹配器来比较扩展.有一些可用,它们在这里很有用.需要在测试模式中确保生成的符号在需要时是相同的.

还有s-expression diff工具.例如diff-sexp.

推荐阅读
手机用户2402852387
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有