我试图弄清楚如何将3个变量合并到球拍的尾部递归代码中

时间:2019-04-12 01:49:06

标签: scheme lisp racket

编写一个称为popadd的尾递归函数,该函数在时间t = 0时用P个人口建模,每年增加d个人口。

(define (popadd t  P)
  (if (= t 0)
      P
  (+(popadd( - t 1) P)d)) 
)

但是,当然,我得到的错误是d尚未定义,这是事实。我尝试将其添加为输入,但作为返回,我得到了为D插入的数字。

2 个答案:

答案 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)))

真的希望,那些试图教编程的人知道足够的数学知识,可以解决那些琐碎的闭式答案,因为这样做会鼓励人们写效率低下的代码(在复杂度级别上)。显然这不是您的错:是您老师的错。