如何像这样进入SBCL? 使用 LispWorks跟踪和打印

问题描述

我是 Common Lisp 的新手,我正在使用 SBCL、Slime 和 Emacs 来学习。

在阅读Common Lisp: A Gentle Introduction to Symbolic Computation这本书时,作者提到了有助于调试并且能够做到这一点的 STEP 工具:

enter image description here

斜体文本是来自作者还是工具本身并不是 100% 清楚的。可能只是作者的评论。

然而,即使我不考虑斜体,我也无法生成这样的描述信息。

如果我使用只使用 SBCL 的 REPL,我会得到:

* (step (if (oddp 5) 'yes 'no))            
YES

如果我在启用 Slime 的情况下在 Emacs 中使用 REPL,我会得到:

CL-USER> (step (if (oddp 5) 'yes 'no))
YES

作者说:

Common Lisp 的每个实现都提供了它自己的版本 工具;只是名称已标准化。

如果我在 Emacs/Slime 中用一个函数尝试同样的事情,我会得到更多信息:

(defun my-abs (x)
  (cond ((> x 0) x)
    ((< x 0) (- x))
    (t 0)))

在 REPL 上使用上面的定义和下面的命令:

CL-USER> (step (my-abs 10))

我明白了:

Evaluating call:
  (MY-ABS 10)
With arguments:
  10
   [Condition of type STEP-FORM-CONDITION]

Restarts:
 0: [STEP-CONTINUE] Resume normal execution
 1: [STEP-OUT] Resume stepping after returning from this function
 2: [STEP-NEXT] Step over call
 3: [STEP-INTO] Step into call
 4: [RETRY] Retry SLIME REPL evaluation request.
 5: [*ABORT] Return to SLIME's top level.
 --more--

Backtrace:
  0: ((LAMBDA ()))
  1: (SB-INT:SIMPLE-EVAL-IN-LEXENV (LET ((SB-IMPL::*STEP-OUT* :MAYBE)) (UNWIND-PROTECT (SB-IMPL::WITH-STEPPING-ENABLED #))) #S(SB-KERNEL:LEXENV :FUNS NIL :VARS NIL :BLOCKS NIL :TAGS NIL :TYPE-RESTRICTIONS ..
  2: (SB-INT:SIMPLE-EVAL-IN-LEXENV (STEP (MY-ABS 10)) #<NULL-LEXENV>)
  3: (EVAL (STEP (MY-ABS 10)))
 --more--

不幸的是,这些选项似乎都没有给我想要的东西(这可能是我的理解错误)。

我想看到类似的东西:

enter image description here

SLIME 似乎是一个彻底的工具。我可能遗漏了一些东西。

有没有办法使用 SLIME 或 SBCL 生成与书中描述的相同的输出?

解决方法

正如上面有人建议的那样,SBCL 在默认情况下确实优化了很多,并且默认编译。这是我为创建示例所做的工作:

  • 我首先通过运行为“建议的优化”弥补了“错误的价值”
(declaim (optimize (debug 3) (space 0) (speed 0)))
  • 然后,我定义了一个函数,不仅仅是一个 if 条件,因为这种东西总是内联的,不幸的是(尽管你可能会尝试 (declaim (notinline ...)),我没有。一种方法是创建一个调用另一个函数的函数,例如:
(defun foo () "hey!")

(defun bar () (foo))
  • 现在,当我运行 (step (bar)) 时,我会看到您在上面的问题中共享的调试器窗格,如果我现在选择选项 #3,进入 em>,我得到了相同的窗格,但正如预期的那样,现在专注于对 foo 的调用。

祝你好运!

一些参考:

,

看起来作者正在使用 LispWorks 的步进器。

使用 LispWorks

这是我的步进会话,使用 :s 步进当前表单及其所有子表单。

CL-USER 5 > (step (my-abs -5))
(MY-ABS -5) -> :s
   -5 -> :s
   -5 
   (COND ((> X 0) X) ((< X 0) (- X)) (T 0)) <=> (IF (> X 0) (PROGN X) (IF (< X 0) (- X) (PROGN 0)))
   (IF (> X 0) (PROGN X) (IF (< X 0) (- X) (PROGN 0))) -> :s
      (> X 0) -> :s
         X -> :s
         -5 
         0 -> :s
         0 
      NIL 
      (IF (< X 0) (- X) (PROGN 0)) -> :s
         (< X 0) -> :s
            X -> :s
            -5 
            0 -> :s
            0 
         T 
         (- X) -> :s
            X -> :s
            -5 
         5 
      5 
   5 
5 
5

帮助在 :? 上:

 :?

:s       Step this form and all of its subforms (optional +ve integer arg)
:st      Step this form without stepping its subforms
:si      Step this form without stepping its arguments if it is a function call
:su      Step up out of this form without stepping its subforms
:sr      Return a value to use for this form
:sq      Quit from the current stepper level
:bug-form <subject> &key <filename>
         Print out a bug report form,optionally to a file.
:get <variable> <command identifier>
         Get a previous command (found by its number or a symbol/subform within it) and put it in a variable.
:help    Produce this list.
:his &optional <n1> <n2>
         List the command history,optionally the last n1 or range n1 to n2.
:redo &optional <command identifier> 
         Redo a previous command,found by its number or a symbol/subform within it.
:use <new> <old> &optional <command identifier> 
         Do variant of a previous command,replacing old symbol/subform with new symbol/subform.

对于已编译的代码,它还有一个可视化的步进器,您可以在其中按红色按钮设置断点,查看中间变量的变化等。它看起来像这样:

LispWorks 是一个专有的实现和 IDE,有一个免费但有限的版本。我刚刚写了 a review,应该合并到 Cookbook 中。

跟踪和打印

你知道trace吗? printv 是一个外部库,是类固醇的踪迹。它们类似于您欣赏的输出。

(defun factorial (n)
  (if (plusp n)
    (* n (factorial (1- n)))
    1))
(trace factorial)

(factorial 2)
  0: (FACTORIAL 3)
    1: (FACTORIAL 2)
      2: (FACTORIAL 1)
        3: (FACTORIAL 0)
        3: FACTORIAL returned 1
      2: FACTORIAL returned 1
    1: FACTORIAL returned 2
  0: FACTORIAL returned 6
6

(untrace factorial)

printv 打印代码和返回值。

(printv:printv
           (+ 2 3)              
           *print-case*
           *package*
           'symbol
           (let* ((x 0) (y (1+ x)) (z (1+ y)))
             (values x y z)))
;;;   (+ 2 3) => 5
;;;   *PRINT-CASE* => :UPCASE
;;;   *PACKAGE* => #<PACKAGE "ISSR-TEST">
;;;   'SYMBOL => SYMBOL
;;;   (LET* ((X 0) (Y (1+ X)) (Z (1+ Y)))
        (VALUES X Y Z)) =>
           [ [X=0]  [Y=1]  [Z=2] ]
;;;   => 0,1,2

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...