关闭尾调用优化以在 Chez Scheme 中进行调试

Turn off tail call optimization for debugging in Chez Scheme

我正在 Chez Scheme 中调试以下程序。

(define (proc3 x3)
  (printf "proc3 ~a\n" (+ 1 x3)))

(define (proc2 x2)
  (printf "proc2 ~a\n" x2)
  (proc3 x2))

(define (proc1 x1)
  (printf "proc1 ~a\n" x1)
  (proc2 x1))

(proc1 'a)

运行 这个程序会报错。

(debug) 该程序产生以下信息:

$ scheme
Chez Scheme Version 9.5
Copyright 1984-2017 Cisco Systems, Inc.

> (load "debugging.scm")
proc1 a
proc2 a
Exception in +: a is not a number
Type (debug) to enter the debugger.
> (debug)
debug> i
#<continuation in proc3>                                          : sf
  0: #<continuation in proc3>
  1: #<system continuation in ksrc>
  2: #<system continuation>
  3: #<system continuation in dynamic-wind>
  4: #<system continuation in dynamic-wind>
  5: #<system continuation in $reset-protect>
  6: #<system continuation in new-cafe>
#<continuation in proc3>                                          :

请注意,堆栈帧仅包含最后一帧 proc3,但我想显示 proc2proc1。这似乎是由于 Scheme 的 TCO(尾调用优化)阻止调试器检查精确的调用堆栈帧。

如果我把调用(proc3 x2)(proc2 x1)放在尾部位置,调试器可以正常打印精确的调用堆栈帧。

(define (proc3 x3)
  (printf "proc3 ~a\n" (+ 1 x3)))

(define (proc2 x2)
  (printf "proc2 ~a\n" x2)
  (proc3 x2)
  (printf "proc2 leave\n"))

(define (proc1 x1)
  (printf "proc1 ~a\n" x1)
  (proc2 x1)
  (printf "proc1 leave\n"))

(proc1 'a)
$ scheme
Chez Scheme Version 9.5
Copyright 1984-2017 Cisco Systems, Inc.

> (load "debugging.scm")
proc1 a
proc2 a
Exception in +: a is not a number
Type (debug) to enter the debugger.
> (debug)
debug> i
#<continuation in proc3>                                          : sf
  0: #<continuation in proc3>
  1: #<continuation in proc2>
  2: #<continuation in proc1>
  3: #<system continuation in ksrc>
  4: #<system continuation>
  5: #<system continuation in dynamic-wind>
  6: #<system continuation in dynamic-wind>
  7: #<system continuation in $reset-protect>
  8: #<system continuation in new-cafe>
#<continuation in proc3>                                          :

Chez Scheme有没有办法暂时关闭TCO? (仅供调试)

谢谢。

这肯定是不可能的,因为方案规范强加尾递归调用成为迭代过程。

在实现中,有一个 APPLY return code 会丢弃通过尾递归进行的迭代过程的堆栈帧——解释器会 SCODE 检查 "NULL == CDR(SCODE)" 作为一个特殊的返回 APPLY.

类型代码的条件

如果你想像你一样发生,你可以在eval中修改这个条件并重新编译方案——它将不再是方案。

如果要调试,可以套用其他方法。