printf命令是一种尝试调试的合理方式,还是其他技术会更快和/或更精确?
(假设是#39; m使用Racket或其他允许printf的方言)。
答案 0 :(得分:2)
首先关闭。方案(R7RS,R6RS,R5RS)没有printf
。有display
和SRFI-28 format
。因此,我只会将printf
视为打印语句,这可能意味着您只是使用display
。
正确答案是您的代码应该制作成可以轻松进行单元测试的小程序。如果你这样做,你将永远不需要调试器或再次打印出调试信息。
通常,Scheme使用表达式,只需添加一个print语句而不必在begin
中包装它和以下语句并不总是很容易。因此,您可能会在添加时引入错误,更糟糕的是,从代码中删除调试信息。例如。
(if (test arg)
(call-something (car arg))
(call-something-else (cdr arg))
那么为了在不改变代码的过程的情况下打印(test arg)
的结果需要更改多少,以及在不引入新错误的情况下删除它的容易程度如何?如果我真的想打印调试信息,我会做一个宏:
(define-syntax dbg
(syntax-rules ()
((_ . rest)
(let ((expr 'rest)
(res rest))
(display (list expr '=> res))
res))))
现在你可以在{1}}前面加上你要检查的地方:
dbg
想象一下,结果og (if (dbg test arg)
(call-something (car arg))
(call-something-else (cdr arg))
为(test arg)
,然后您将5
输出,而不会将结果更改为((test arg) => 5)
。
如果您碰巧使用DrRacket,使用非常好的调试器和宏步进器非常简单。有了它,您只需设置一个断点并向有趣的部分运行,然后逐步查看每个步骤计算的值。可能还有一些其他的IDE,但我停止了我发现球拍。即使在使用DrRacket时,没有任何东西可以阻止您在生产中使用不同的实现,例如Ikarus,前提是您在其中一个Scheme报告中写入而不是特定于实现的内容。
小心!对调试器太熟悉的人倾向于制作看起来更像FORTRAN而不是Scheme的长程序。最好的方法是编写程序,就好像你没有任何调试方法一样,在你觉得需要时使用调试器,如果你发现自己一直在调试器中,重构你的代码。