断尾递归?

时间:2013-06-16 17:42:11

标签: programming-languages scheme tail-recursion

我学过编程语言课程,我在幻灯片中有这个Scheme代码的变体:

; (listof any) -> (listof any[no-cons])

(define (remove-pairs l)
  (cond
    [(empty? l) '()]
    [else
      (let ([ans
              (if (cons? (first l))
                  (begin (free! (first l))
                         (remove-pairs (rest l)))
                  (cons (first l)
                        (remove-pairs (rest l))))])
       (free! l) ; <- this will break our tail recursion.
       ans)]))

在代码中,(free! l)会破坏我们的尾递归。我不知道这个功能是做什么的,我没有任何意义。

1 个答案:

答案 0 :(得分:0)

如果没有看到free!的代码,就不可能知道这个函数应该做什么。可以推断的是,过程删除列表中不是cons单元格的每个元素,构建并返回一个只包含非{{1}元素的新列表从一开始就是细胞。

声明函数是尾递归是不正确的 - 它永远不会开始,无论cons做什么,递归调用都不在尾部位置。

这是使用尾递归实现推断功能的正确的方法,请注意问题中递归的结构完全错误,而不是尾递归:

free!

从更实际的角度来看,你可以使用(define (remove-pairs l) (let loop ((lst (reverse l)) (acc '())) (cond [(empty? lst) acc] [(cons? (first lst)) (free! (first lst)) ; whatever that is (loop (rest lst) acc)] [else (loop (rest lst) (cons (first lst) acc))]))) 获得相同的功能,虽然这不能保证是尾递归的:

filter

无论哪种方式,这都是它的工作原理:

(define (remove-pairs l)
  (filter (lambda (x)
            (cond [(cons? x)
                   (free! x) ; whatever that is
                   #f]
                  [else #t]))
          l))