这个函数尾递归吗?

时间:2013-03-18 00:55:00

标签: lisp scheme racket tail-recursion

球拍中,我定义了以下函数,我想知道它是否是尾递归

(define foo
  (λ (c m s1 s2)
      (if (< c m)
          (if (= (modulo m c) 0)
              (foo (+ c 1) m (+ s1 c) s2)
              (foo (+ c 2) m s1 (+ s2 c)))
          (cons s1 s2))))

我的问题实际上是这样的,但我必须写一些其他内容来满足我的帖子质量标准。实际上,我不知道我的帖子质量标准是什么

4 个答案:

答案 0 :(得分:5)

这与您之前的问题几乎相同。是的,这是尾递归的:只要在函数foo中发生递归调用,它就处于尾部位置。含义:在执行递归调用之后,没有别的事情可做,执行的分支结束。 (cons s1 s2)部分是递归的基本情况,因此它不计算在内。为了更清楚地看到它,foo程序等同于:

(define (foo c m s1 s2)
  (cond ((>= c m)
         (cons s1 s2))                  ; base case of recursion
        ((= (modulo m c) 0)
         (foo (+ c 1) m (+ s1 c) s2))   ; recursive call is in tail position
        (else
         (foo (+ c 2) m s1 (+ s2 c))))) ; recursive call is in tail position

让我们看一下尾部递归的示例。例如,如果第二个if的后续部分定义如下:

(+ 1 (foo (+ c 1) m (+ s1 c) s2))

然后显然递归调用不会处于尾部位置,因为在递归返回后执行一个操作:在递归结果中添加一个。

答案 1 :(得分:1)

这是一个伪代码(实际上是Common Lisp)将你的代码翻译成帧变异版本:

(defun foo (c m s1 s2)
  (prog 
      ((c c) (m m) (s1 s1) (s2 s2))  ; the frame
      BACK
      (if (< c m)
          (if (= (modulo m c) 0)
              (progn 
                (psetf s1 (+ s1 c)     ; set!
                       c  (+ c  1))    ;   in parallel
                (go BACK))
              (progn 
                (psetf s2 (+ s2 c)     ; set!
                       c  (+ c  2))    ;   in parallel
                (go BACK)))
          (return-from foo (cons s1 s2))))))

由于在每次尾调用后没有什么可做的,我们只能(go BACK)

答案 2 :(得分:0)

foo的唯一调用位于尾部位置,因此该函数看起来像尾递归。

答案 3 :(得分:0)

Scheme R6RS第59页第11.20节描述尾调用并显示基本Scheme语法形式的尾调用位置,例如iflambda

您在foo内对foo的来电处于尾部位置。 (因为它们位于内部if尾部位置,外部if尾部位置和lambda尾部位置。)