debug ¶假设你写了一个函数,用于计算从 1 到指定数字的累加和。(即之前讲过的 triangle 函数。See Example with Decrementing Counter。)
但函数定义存在错误:你把 ‘1-’ 误写成了 ‘1=’。错误定义如下:
(defun triangle-bugged (number)
"返回数字 1 到 NUMBER 的累加和。"
(let ((total 0))
(while (> number 0)
(setq total (+ total number))
(setq number (1= number))) ; Error here.
total))
如果你在 Info 中阅读本文,可以按常规方式执行该定义,回显区会出现 triangle-bugged。
现在以 4 为参数执行 triangle-bugged 函数:
(triangle-bugged 4)
会创建并进入 *Backtrace* 缓冲区,内容如下:
---------- Buffer: *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) ---------- Buffer: *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=)
你可以修正错误,重新执行函数定义,再进行测试。