一个追踪通常会根据调用树来缩进。在一个做遍历的函数,像下面这个函数,它给一个树的每一个非空元素加上 1,
一个树的形状会因此反映出它被遍历时的数据结构:
一个更灵活的追踪办法是在你的代码里插入诊断性的打印语句。如果已经知道结果了,这个经典的方法大概会与复杂的调适工具一样被使用数十次。这也是为什么可以互动地重定义函数式多么有用的原因。
一个回溯 (backtrace)是一个当前存在栈的调用的列表,当一个错误中止求值时,会由一个中断循环生成此列表。如果追踪像是”让我看看你在做什么”,一个回溯像是询问”我们是怎么到达这里的?” 在某方面上,追踪与回溯是互补的。一个追踪会显示在一个程序的调用树里,选定函数的调用。一个回溯会显示在一个程序部分的调用树里,所有函数的调用(路径为从顶层调用到发生错误的地方)。
出现在回溯里的臭虫较容易被发现。你可以仅往回检查调用链,直到你找到第一个不该发生的事情。另一个函数式编程 (2.12 节)的好处是所有的臭虫都会在回溯里出现。在纯函数式代码里,每一个可能出错的调用,在错误发生时,一定会在栈出现。
一个回溯每个实现所提供的信息量都不同。某些实现会完整显示一个所有待调用的历史,并显示参数。其他实现可能仅显示调用历史。一般来说,追踪与回溯解释型的代码会得到较多的信息,这也是为什么你要在确定你的程序可以工作之后,再来编译。