编写一个称为popadd的尾递归函数,该函数在时间t = 0时用P个人口建模,每年增加d个人口。
(define (popadd t P)
(if (= t 0)
P
(+(popadd( - t 1) P)d))
)
但是,当然,我得到的错误是d尚未定义,这是事实。我尝试将其添加为输入,但作为返回,我得到了为D插入的数字。
答案 0 :(得分:3)
您可以简单地将另一个参数传递给递归:
(define (popadd t P d)
(if (= t 0)
P
(+ d (popadd (- t 1) P d))))
或者您可以定义该值,以免传递它-假设它不需要更改:
(define d 100)
(define (popadd t P)
(if (= t 0)
P
(+ d (popadd (- t 1) P))))
请注意,如果可以的话,您可以对P
执行相同的操作。这实际上取决于该程序的预期合同。
答案 1 :(得分:2)
请注意,您的代码或其他答案中的代码都不是尾部递归:在像(+ (f ...))
这样的递归调用中,f
不在尾部位置。要使代码尾部递归,您需要将递归调用的结果作为整个调用的结果(因此,在上面的示例中,+
是处于尾部位置)。为此,您需要一个辅助功能。这是一种仅依赖于本地define
的方式:
(define (popadd t P d)
(define (popadd-loop tau pop)
(if (zero? tau)
pop
(popadd-loop (- tau 1) (+ pop d))))
(popadd-loop t P))
使用named-let
本质上是同一件事,这更好:
(define (popadd t P d)
(let popadd-loop ([tau t] [pop P])
(if (zero? tau)
pop
(popadd-loop (- tau 1) (+ pop d)))))
最后请注意,此问题有一个封闭的解决方案:
(define (popadd t P d)
(+ P (* t d)))
我真的希望,那些试图教编程的人知道足够的数学知识,可以不解决那些琐碎的闭式答案,因为这样做会鼓励人们写效率低下的代码(在复杂度级别上)。显然这不是您的错:是您老师的错。