我攻读圣诞节测试,并做一些样品的考题,我遇到这一个有我有点难倒
我可以做定期的递归很好,但我不能换我周围的头如何使用尾递归来写同样的事情。
普通版本:
(define (factorial X)
(cond
((eqv? X 1) 1)
((number? X)(* X (factorial (- X 1))))))
我攻读圣诞节测试,并做一些样品的考题,我遇到这一个有我有点难倒
我可以做定期的递归很好,但我不能换我周围的头如何使用尾递归来写同样的事情。
普通版本:
(define (factorial X)
(cond
((eqv? X 1) 1)
((number? X)(* X (factorial (- X 1))))))
对于函数是尾递归,必须有什么不同之处返回其值的函数返回后做。 也就是说,发生在递归步骤的最后一件事是调用函数本身。 这通常是通过使用跟踪答案的蓄电池参数来实现的:
(define (factorial x acc)
(if (zero? x)
acc
(factorial (sub1 x) (* x acc))))
上述过程将首先调用1
为蓄压器,这样的:
(factorial 10 1)
=> 3628800
请注意,累积值被达到的基本情况时返回,将acc
参数会在递归调用每个点更新。 我只好一个额外的参数添加到程序,但是这可以通过限定内部程序或命名来避免let
,例如:
(define (factorial x)
(let loop ((x x)
(acc 1))
(if (zero? x)
acc
(loop (sub1 x) (* x acc)))))