Здається, я знайшов загальний спосіб перетворити будь-яку рекурсивну процедуру в хвостову рекурсію:
- Визначте допоміжну допоміжну процедуру з додатковим параметром "результат".
- Застосуйте те, що було б застосовано до зворотного значення процедури до цього параметра.
- Для початку зателефонуйте на цю процедуру допомоги. Початкове значення параметра "результат" - це значення для точки виходу рекурсивного процесу, так що отриманий ітераційний процес починається з того місця, де рекурсивний процес починає скорочуватися.
Наприклад, ось оригінальна рекурсивна процедура, яку потрібно перетворити ( SICP, вправа 1.17 ):
(define (fast-multiply a b)
(define (double num)
(* num 2))
(define (half num)
(/ num 2))
(cond ((= b 0) 0)
((even? b) (double (fast-multiply a (half b))))
(else (+ (fast-multiply a (- b 1)) a))))
Ось перетворена хвостово-рекурсивна процедура ( вправа SICP 1.18 ):
(define (fast-multiply a b)
(define (double n)
(* n 2))
(define (half n)
(/ n 2))
(define (multi-iter a b product)
(cond ((= b 0) product)
((even? b) (multi-iter a (half b) (double product)))
(else (multi-iter a (- b 1) (+ product a)))))
(multi-iter a b 0))
Хтось може це довести чи спростувати?
b
силою 2 показує, що спочатку встановлення product
0 не зовсім правильне; але змінити його на 1 не працює, коли b
це непарно. Можливо, вам потрібні 2 різні параметри акумулятора?