Lisp 为什么尾部递归Collatz猜想会导致Scheme中的堆栈溢出?

Lisp 为什么尾部递归Collatz猜想会导致Scheme中的堆栈溢出?,lisp,scheme,stack-overflow,guile,collatz,Lisp,Scheme,Stack Overflow,Guile,Collatz,我在Scheme中写过Collatz猜想: (define C (lambda (n) (cond ((eq? n 1) 1) ((even? n) (C (/ n 2))) (else (C (+ (* n 3) 1)))))) 这是一个尾部递归调用,但在调用(C 121)时会出现堆栈溢出: 为什么正确的尾部递归会导致溢出?如您所见,我将Guile用作Scheme解释器(版本1.8.7) 看起来它总是返回1(或者无限循环——这一猜想尚未得到证实)。在

我在Scheme中写过Collatz猜想:

(define C
  (lambda (n)
    (cond
     ((eq? n 1) 1)
     ((even? n) (C (/ n 2)))
     (else (C (+ (* n 3) 1))))))
这是一个尾部递归调用,但在调用(C 121)时会出现堆栈溢出:

为什么正确的尾部递归会导致溢出?如您所见,我将Guile用作Scheme解释器(版本1.8.7)


看起来它总是返回
1
(或者无限循环——这一猜想尚未得到证实)。在递归调用周围隐藏
(+1…
是否存在转录错误?

定义的过程在Racket中运行良好。对我来说,这似乎是一个bug,或者是非常特定于您的环境的东西


几乎肯定与您的问题无关,但有点吹毛求疵:对数字使用比较
(=n1)
,而不是
(eq?n1)

当您不跟踪函数调用时会发生什么?当您使用另一个方案系统时会发生什么?禁用跟踪没有帮助。Racket在给定的示例中做得很好。这可能是一个bug:该定义看起来是递归的。(不过,大多数跟踪库都会破坏尾部递归性。)我在ubuntu上试过这个,看起来效果不错。您正在使用哪个操作系统?这是在openSUSE 11.3上,但我认为这可能是Guile旧版本的错误(2.x版本可用,但不适用于我的系统)。无论如何,如果这个定义是正确的,即一切正常,我担心我误解了关于尾部递归的某些内容。
guile> (trace C)
(C)
guile> (C 121)
[C 121]
[C 364]
[C 182]
[C 91]
[C 274]
[C 137]
[C 412]
[C 206]
[C 103]
[C 310]
[C 155]
[C 466]
[C 233]
[C 700]
[C 350]
[C 175]
[C 526]
[C 263]
[C 790]
[C 395]
[C 1186]
ERROR: Stack overflow
ABORT: (stack-overflow)
(define C
  (lambda (n)
    (cond
     ((eq? n 1) 1)
     ((even? n) (C (/ n 2)))
     (else (C (+ (* n 3) 1))))))