在球拍中,我定义了以下函数,我想知道它是否是尾递归:
(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))))
我的问题实际上是这样的,但我必须写一些其他内容来满足我的帖子质量标准。实际上,我不知道我的帖子质量标准是什么。
答案 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语法形式的尾调用位置,例如if
和lambda
您在foo
内对foo
的来电处于尾部位置。 (因为它们位于内部if
尾部位置,外部if
尾部位置和lambda
尾部位置。)