debugging 如何单步执行一些Common Lisp代码,检查表单的返回值?

icomxhvb  于 2023-05-18  发布在  其他
关注(0)|答案(1)|浏览(158)

也许这是菜鸟,但我失去了我的头脑后,这一点。我非常惊讶地发现CL的stepper并不显示各种形式的返回值。我的意思是,调试器可以检查帧,REPL允许手动检查变量,但例如在以下代码中

(defun fact (n)
  (if (<= n 0)
      1
      (* n (fact (- n 1)))))

(fact 5)

我不能指示调试器说“嘿,我刚刚跳过了表单(<= n 0),它返回了nil,然后我又跳过了(- n 1),它返回了值4”。这可以在Emacs-lisp和Clojure中完成(我使用Emacs,但它不是我感兴趣的接口)。我知道存在(step)的形式,但它依赖于实现,并且我在SBCL和CMU上都看到它并没有实现我的意思。所以我的问题是,**CL的调试器可以做到这一点(步进+打印值刚刚评估)?**如果是,是否只有一个实现?你能提供MWE吗?
谢谢!

e5nqia27

e5nqia271#

Common Lisp是一种语言规范,而不是实现。因此,像'CL's stepper'或'CL's debugger'这样的表达式是类别错误:语言没有步进器或调试器,实现有。语言规范提供了一个接口step,通过它可以调用这样的东西,但是说
step实现了一种调试范例,其中允许程序员逐步完成表单的评估。交互的特定性质(包括使用哪些I/O流以及单步执行是否具有词法或动态范围)是由实现定义的。
因此,您的问题的答案是否定的,“CL的调试器”不能这样做,因为“CL的调试器”不存在。
语言的 * 实现 * 可能会或多或少地对此提供支持。例如,我知道LispWorks是这样的。我不知道其他实现是否会这样做。CL作为一种语言也足够反射,可以编写一个便携式步进器:sly-stepper可能是这样的,但我不确定。
以下是LW非IDE步进器的使用示例:

CL-USER 7 > (step (let ((x 0)) (/ (sin x) x)))
(let ((x 0)) (/ (sin x) x)) -> :su

Error: Division-by-zero caused by / of (0.0 0.0).
  1 (continue) Return a value to use.
  2 Supply new arguments to use.
  3 (abort) Return to debug level 1.
  4 Return to stepper level 1.
  5 Quit from stepper.
  6 Return to debug level 0.
  7 Restart top-level loop.

Type :b for backtrace or :c <option number> to proceed.
Type :bug-form "<subject>" for a bug report template or :? for other options.

CL-USER 9 : 2 > :a
(let ((x 0)) (/ (sin x) x)) -> :sr 0.0
0.0 
0.0

CL-USER 8 > (step (let ((x 0)) (/ (sin x) x)))
(let ((x 0)) (/ (sin x) x)) -> :s 2
   0
   0 
   (/ (sin x) x)
      (sin x) -> :si
      0.0 
      x -> :sr 1
      1 
   0.0 
0.0 
0.0

在第一次交互中,我让它运行,直到它得到错误,从那里中止回到步进器,然后告诉步进器返回零。在第二个例子中,我逐步执行,直到它要计算x,然后告诉它计算的结果是1,导致它返回零。
上面的非IDE步进器在这里记录& IDE步进器在这里。

相关问题