2012-03-16 4 views
6

Я написал Коллатца гипотезу на схеме:Почему хвостовая рекурсивная гипотеза 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 как интерпретатор схемы (версия 1.8.7).

+0

Что происходит, когда вы не отслеживаете вызов функции? Что происходит, когда вы используете другую систему схем? – knivil

+0

Отключение трассировки не помогает. Ракетка отлично справляется с данным примером. –

+7

Это может быть ошибка: это определение выглядит хвостовым рекурсивным. (Большинство библиотек трассировки уничтожают хвостовую рекурсивность.) –

ответ

2

Процедура, как определено, работает нормально в Racket. Это кажется ошибкой для меня, или что-то очень специфическое для вашей среды.

Почти наверняка не имеет отношения к вашей проблеме, но немного выбора: используйте сравнение (= n 1) для чисел вместо (eq? n 1).

0
(define C 
    (lambda (n) 
    (cond 
    ((eq? n 1) 1) 
    ((even? n) (C (/ n 2))) 
    (else (C (+ (* n 3) 1)))))) 

Это выглядит, как он всегда возвращает 1 (или петли бесконечно - гипотеза остается недоказанной). Есть ли ошибка транскрипции, скрывающая (+1 ...) вокруг рекурсивных вызовов?