首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >怎么才能像这样踏入SBCL?

怎么才能像这样踏入SBCL?
EN

Stack Overflow用户
提问于 2021-05-18 18:07:37
回答 2查看 346关注 0票数 3

我对通用Lisp很陌生,我正在使用SBCL、Slime和Emacs来学习。

在阅读“通用Lisp:符号计算的绅士介绍”一书时,作者提到了STEP工具,它有助于调试并能够做到这一点:

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

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

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

代码语言:javascript
复制
* (step (if (oddp 5) 'yes 'no))            
YES

如果我使用Emacs中的REPL和Slime,我得到:

代码语言:javascript
复制
CL-USER> (step (if (oddp 5) 'yes 'no))
YES

提交人说:

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

如果我在Emacs/Slime中尝试使用相同的功能,我会得到更多的信息:

代码语言:javascript
复制
(defun my-abs (x)
  (cond ((> x 0) x)
    ((< x 0) (- x))
    (t 0)))

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

代码语言:javascript
复制
CL-USER> (step (my-abs 10))

我得到:

代码语言:javascript
复制
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--

不幸的是,这些选择似乎没有给我我想要的(这可能是一个错误的解释对我的一方)。

我希望看到这样的情况:

黏液似乎是一个彻底的工具。我可能漏掉了什么。

是否有一种方法可以使用SLIME或SBCL生成与该书描述的输出相同的输出?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-05-19 08:20:11

看起来,作者使用的是LispWorks的步骤。

用LispWorks

下面是我的步骤会话,使用:s对当前表单及其所有子表单进行分步。

代码语言:javascript
复制
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

帮助在:?

代码语言:javascript
复制
 :?

: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,它有一个免费但有限的版本。我刚刚写了评议,应该合并到烹饪簿上。

跟踪和打印

你认识trace吗?印字,一个外部库,是类固醇的痕迹。它们类似于你所欣赏的输出。

代码语言:javascript
复制
(defun factorial (n)
  (if (plusp n)
    (* n (factorial (1- n)))
    1))
代码语言:javascript
复制
(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打印代码和返回的值。

代码语言:javascript
复制
(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
票数 2
EN

Stack Overflow用户

发布于 2021-05-19 06:07:20

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

  • 我首先通过运行“建议的优化”来弥补“坏值”。
代码语言:javascript
复制
(declaim (optimize (debug 3) (space 0) (speed 0)))
  • 然后,我定义了一个函数,它不仅仅是一个if条件,因为这类事情总是内联的,不幸的是(尽管您可能尝试过(declaim (notinline ...)),但我没有这样做。一种方法是创建一个调用另一个函数的函数,比如:
代码语言:javascript
复制
(defun foo () "hey!")

(defun bar () (foo))
  • 现在,当我运行(step (bar))时,我看到了您在上面的问题中共享的调试器窗格,如果我现在选择选项#3,进入,我会得到相同的窗格,但现在像希望的那样将焦点集中在对foo的调用上。

祝好运!

一些参考资料:

  • “单步”手册:http://www.sbcl.org/manual/#Single-Stepping
  • “调试器策略控制”手册:http://www.sbcl.org/manual/#Debugger-Policy-Control
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67591748

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档