debug
假设你已经编写了一个函数定义,该函数旨在返回给定数字范围内数字的总和。 (这是先前讨论的 triangle
函数。See 具有递减计数器的示例, 进行讨论。)
然而,你的函数定义中存在一个错误。你误将 ‘1=’ 写成了 ‘1-’。以下是有问题的定义:
(defun triangle-bugged (number)
"返回1到NUMBER(含)的数字之和。"
(let ((total 0))
(while (> number 0)
(setq total (+ total number))
(setq number (1= number))) ; 这里有错误。
total))
如果你在Info中阅读这个,可以以正常方式评估这个定义。你将在回显区域看到 triangle-bugged
。
现在用参数4评估 triangle-bugged
函数:
(triangle-bugged 4)
这将创建并进入一个 *Backtrace* 缓冲区,显示:
---------- 缓冲区: *Backtrace* ---------- Debugger entered--Lisp error: (void-function 1=) (1= number) (setq number (1= number)) (while (> number 0) (setq total (+ total number)) (setq number (1= number))) (let ((total 0)) (while (> number 0) (setq total ...) (setq number ...)) total) triangle-bugged(4)
eval((triangle-bugged 4) nil) eval-expression((triangle-bugged 4) nil nil 127) funcall-interactively(eval-expression (triangle-bugged 4) nil nil 127) call-interactively(eval-expression nil nil) command-execute(eval-expression) ---------- 缓冲区: *Backtrace* ----------
(我稍微重新格式化了这个示例;调试器不会折叠长行。通常情况下,你可以在 *Backtrace* 缓冲区中键入 q 退出调试器。)
在实践中,对于这么简单的错误,Lisp错误行会告诉你正确的信息来修正定义。函数 1=
是无效的。
然而,假设你不太确定发生了什么?你可以阅读完整的回溯信息。
Emacs会自动启动调试器并将你放在 *Backtrace* 缓冲区中。你也可以按照下面的描述手动启动调试器。
从下到上阅读 *Backtrace* 缓冲区;它告诉你导致错误的Emacs操作。Emacs进行了对 C-x C-e(eval-last-sexp
)的交互调用,这导致了对 triangle-bugged
表达式的评估。每一行以上告诉你Lisp解释器接下来评估了什么。
从缓冲区底部开始数第三行是
(setq number (1= number))
Emacs试图评估这个表达式;为了这样做,它试图评估缓冲区从上到下显示的内部表达式:
(1= number)
这就是错误发生的地方;正如最上面的行所说:
Debugger entered--Lisp error: (void-function 1=)
你可以纠正错误,重新评估函数定义,然后再次运行你的测试。