这个方案代码尾递归吗?

时间:2013-03-26 22:23:01

标签: scheme tail-recursion r5rs

编辑:谢谢大家。我是这门语言的新手(刚开始使用它两天前),所以这就是为什么我不熟悉conds。如果我有时间,我可以重写它,但我只是想确保我的基本逻辑正确。再次感谢!

我的任务是创建一个尾递归函数,从列表中删除第n个元素,1< = n< = listlength,只有两个参数,列表x和元素n。因此,(删除1'(a b c d))将返回(b c d)。我写了以下内容,并希望得到一些保证,它确实是尾递归的。我唯一模糊的是递归调用是否可以嵌套在IF语句中。

(define (remove n x)
  ; if n is 1, just return the cdr 
  (if (and (not (list? (car x))) (= n 1))
     (cdr x)
     ; if the car is not a list, make it one, and call recursively
     (if (not (list? (car x)))
        (remove (- n 1) (cons (list (car x)) (cdr x)))
        ; if n !=1, insert the cadr into the list at the car.
        ; Else, append the list at the car with the cddr
        (if (not(= n 1))
           (remove (- n 1) (cons (append (car x) (list(cadr x))) (cddr x)))
           (append (car x) (cddr x))))))

2 个答案:

答案 0 :(得分:2)

是的,该过程是尾递归的,这意味着:无论何时执行递归调用,它都是在该特定执行分支中发生的最后一件事,在递归返回后没有更多事情要做 - 因此,我们说递归调用位于尾部位置

如果我们使用cond而不是嵌套的if重写过程,可以清楚地看到这一点,在这里您将看到每个执行分支都会导致基本案例或递归案例,并且所有递归调用都处于尾部位置:

(define (remove n x)
         ; base case #1
  (cond ((and (not (list? (car x))) (= n 1))
         ; return from base case, it's not recursive
         (cdr x))
         ; recursive case #1
        ((not (list? (car x)))
         ; recursive call is in tail position
         (remove (- n 1) (cons (list (car x)) (cdr x))))
         ; recursive case #2
        ((not (= n 1))
         ; recursive call is in tail position
         (remove (- n 1) (cons (append (car x) (list(cadr x))) (cddr x))))
         ; base case #2
        (else
         ; return from base case, it's not recursive
         (append (car x) (cddr x)))))

有关为什么if特殊形式的后续/替代部分可以被认为是尾递归的更为技术性的解释,请查看修订后的^ 7报告的当前草案的第3.5节。语言方案 - 语言规范,这里是pdf文件的link(实质上相同的考虑因素适用于R5RS,只是它们在R7RS中有更详细的解释)。特别是:

  

如果以下表达式之一位于尾部上下文中,则显示为⟨tail表达式的子表达式位于尾部上下文中

     

...

     

(if ⟨expression⟩ ⟨tail expression⟩ ⟨tail expression⟩)

     

(if ⟨expression⟩ ⟨tail expression⟩)

答案 1 :(得分:0)

这是关于句法形式的尾递归位置的Scheme规范: enter image description here