【问题标题】:How to debug in [Clozure] Common Lisp?如何在 [Clozure] Common Lisp 中调试?
【发布时间】:2013-08-08 05:38:04
【问题描述】:

我在 Mac 上使用 CCL(1.8.1——撰写本文时可用的最新版本),想知道是否有任何可用的调试教程。

我特别感兴趣的是在我的代码中的某处设置断点,然后戳和刺激各种值,然后跳过下一行代码,检查更多值等等。

编辑: 我已经阅读了 CCL 手册的调试部分(18.3 左右),但不太明白。我来自 C/Java/等。后台和基于 IDE 的源代码级调试器,对 gdb 有一点了解。

所以我想我正在寻找的是一个介绍/教程,它可以引导我完成一些更简单的步骤。

(我是 Lisp(当然还有 CCL)的新手,所以,如果我问的问题完全错误或处理事情的方式完全错误,请随时告诉我。)

谢谢!

【问题讨论】:

    标签: debugging common-lisp


    【解决方案1】:

    我相信 CCL​​ 用户可能会将您指向 Debugging section in the CCL manual,但事实上,ANSI Common Lisp 标准包括出色的调试工具,包括您询问的 breakstepstep 除外)的粒度不是基于一行代码,而是一个表单)。

    其实整个Condition System都值得研究一下。

    还有一个fewtutorials

    要记住的最重要的事情是,调试工具为您提供了正常的 Lisp REPL(读取-评估-打印循环),您可以在其中执行您可以使用初始 REPL 执行的任何操作:定义函数和变量,检查现有的变量(包括在进入调试器的函数中定义的变量)等。 另外,您也许可以在步进器中发出额外的命令,例如stepnext(通常缩写为:s:n)或continue(通常缩写为:c ) 在一个持续的错误中。

    您需要注意的一个区别是,在 gdb 中,您使用 print x(缩写为 p x)检查变量 x,而在 Lisp 中,您只需键入 x 并对其进行评估。

    这里有一些简单的例子:

    步骤

    这里? 提供有关可用命令的帮助;如果您的 lisp barfs,请尝试 help:h

    > (defun factorial (n) (if (zerop n) 1 (* n (factorial (1- n)))))
    FACTORIAL
    > (step (factorial 3))
    step 1 --> (FACTORIAL 3)
    Step 1 > ?
    
    Commands may be abbreviated as shown in the second column.
    COMMAND        ABBR     DESCRIPTION
    Help           :h, ?    print this command list
    Error          :e       print the last error message
    Inspect        :i       inspect the last error
    Abort          :a       abort to the next recent input loop
    Unwind         :uw      abort to the next recent input loop
    Reset          :re      toggle *PACKAGE* and *READTABLE* between the
                              local bindings and the sane values
    Quit           :q       quit to the top-level input loop
    Where          :w       inspect this frame
    Up             :u       go up one frame, inspect it
    Top            :t       go to top frame, inspect it
    Down           :d       go down one frame, inspect it
    Bottom         :b       go to bottom (most recent) frame, inspect it
    Mode mode      :m       set stack mode for Backtrace: 1=all the stack elements
                 2=all the frames                         3=only lexical frames
                 4=only EVAL and APPLY frames (default)   5=only APPLY frames
    Frame-limit n  :fl      set the frame-limit for Backtrace. This many frames
                              will be printed in a backtrace at most.
    Backtrace [mode [limit]] :bt  inspect the stack
    Break+         :br+     set breakpoint in EVAL frame
    Break-         :br-     disable breakpoint in EVAL frame
    Redo           :rd      re-evaluate form in EVAL frame
    Return value   :rt      leave EVAL frame, prescribing the return values
    Step           :s       step into form: evaluate this form in single step mode
    Next           :n       step over form: evaluate this form at once
    Over           :o       step over this level: evaluate at once up to the next return
    Continue       :c       switch off single step mode, continue evaluation
    -- Step-until :su, Next-until :nu, Over-until :ou, Continue-until :cu --
               same as above, specify a condition when to stop
    Step 1 > :s
    step 2 --> 3
    Step 2 > :n
    step 2 ==> value: 3
    step 2 --> (IF (ZEROP N) 1 (* N (FACTORIAL #)))
    Step 2 > :s
    step 3 --> (ZEROP N)
    Step 3 > :n
    step 3 ==> value: NIL
    step 3 --> (* N (FACTORIAL (1- N)))
    Step 3 > :s
    step 4 --> N
    Step 4 > :n
    step 4 ==> value: 3
    step 4 --> (FACTORIAL (1- N))
    Step 4 > :s
    step 5 --> (1- N)
    Step 5 > :n
    step 5 ==> value: 2
    step 5 --> (IF (ZEROP N) 1 (* N (FACTORIAL #)))
    Step 5 > :c
    step 5 ==> value: 2
    step 4 ==> value: 2
    step 3 ==> value: 6
    step 2 ==> value: 6
    step 1 ==> value: 6
    6
    

    请注意,步进器内的提示符是step <level>,其中level 是嵌套级别。

    休息

    > (defun assert-0 (x) (unless (eql x 0) (break "Bad x: ~S" x)) 0)
    ASSERT-0
    > (assert-0 0)
    0
    > (assert-0 'assert-0)
    
    ** - Continuable Error
    Bad x: ASSERT-0
    If you continue (by typing 'continue'): Return from BREAK loop
    The following restarts are also available:
    ABORT          :R1      Abort main loop
    Break 1 > x
    ASSERT-0
    Break 1 > :c
    0
    

    这里的提示是Break <level>

    断言

    > (defun my+1 (x) (assert (numberp x) (x) "must be a number: ~S" x) (1+ x))
    MY+1
    > (my+1 5)
    6
    > (my+1 'my+1)
    
    ** - Continuable Error
    must be a number: MY+1
    If you continue (by typing 'continue'): Input a new value for X.
    The following restarts are also available:
    ABORT          :R1      Abort main loop
    Break 1 > :c
    New X> 'foo
    
    ** - Continuable Error
    must be a number: FOO
    If you continue (by typing 'continue'): Input a new value for X.
    The following restarts are also available:
    ABORT          :R1      Abort main loop
    Break 1 > :c
    New X> 6
    7
    

    assert 使用与break 相同的提示。

    【讨论】:

    • CCL 手册和 Hyperspec 都是很好的参考资料,但我正在寻找更多的手把手,这就是我要求教程的原因。谢谢!
    • +1 以获得非常详细的答案。然而,当我在我的 CCL(1.8 和 1.9)中输入 (step (factorial 3)) 时,我得到了回复 6(3 的答案!)——没有步进。
    • @Olie:最好在专门的 CCL 邮件列表上询问这个 CCL 特定问题。我的猜测是,要么 CCL 仅支持单步执行解释函数并且您的 factorial 已编译,要么这是 CCL 中的一个错误。
    • CCL 不支持 STEP。根据这个 SO:stackoverflow.com/questions/9415000/…
    • 这个答案应该被删除,因为它具有误导性。 CCL 不支持 STEP
    【解决方案2】:

    您正在寻找的简单答案由 juanitofatas 提供。不幸的是,CCL 不支持步进,因此在调试方面很弱。到目前为止,最好的调试实现是 CLISP。

    【讨论】:

    • CCL 不支持步进。投反对票是出于恶意而不是基于证据。下面得到 6 票赞成的答案是完全错误的。
    【解决方案3】:

    在 ccl 中,您可以使用 cl-stepper:step 代替 cl:step

    (ql:quickload "com.informatimago.common-lisp.lisp.stepper")

    【讨论】:

      猜你喜欢
      • 2017-04-25
      • 1970-01-01
      • 1970-01-01
      • 2012-12-16
      • 2010-10-24
      • 2011-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多