私はSchemeでこの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> (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)
なぜ正しい末尾再帰でありますオーバーフローが発生しますか?ご覧のとおり、GuileをSchemeインタプリタ(バージョン1.8.7)として使用しています。
関数呼び出しをトレースしないとどうなりますか?別のスキームシステムを使用するとどうなりますか? – knivil
トレースを無効にすることは役に立ちません。ラケットは与えられた例でうまくいく。 –
これはバグかもしれません:その定義はtail-recursiveです。 (しかし、ほとんどのトレースライブラリはtail-recursivenessを破壊します。) –