Programming languages 断尾递归?

Programming languages 断尾递归?,programming-languages,scheme,tail-recursion,Programming Languages,Scheme,Tail Recursion,我学习过编程语言课程,幻灯片中有一种方案代码: ; (listof any) -> (listof any[no-cons]) (define (remove-pairs l) (cond [(empty? l) '()] [else (let ([ans (if (cons? (first l)) (begin (free! (first l))

我学习过编程语言课程,幻灯片中有一种方案代码:

; (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)]))
;(任何人的列表)->(任何人的列表[无反对意见])
(定义(删除线对l)
(续)
[(空?l)'()]
[其他
(让我们
(如果(反对)(第一个l))
(开始(免费!(第一个l))
(移除配对(其余l)))
(反对(第一个l)
(删除对(其余l)))]

(免费!l)如果不查看
免费!
的代码,就不可能知道这个函数应该做什么。可以推断的是,该过程删除列表中不是
cons
单元格的每个元素,从一开始就创建并返回一个新列表,其中只包含非
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))])))
从更实际的角度来看,您可以使用
过滤器
获得相同的功能,尽管这不能保证是尾部递归的:

(define (remove-pairs l)
  (filter (lambda (x)
            (cond [(cons? x)
                   (free! x) ; whatever that is
                   #f]
                  [else #t]))
          l))
无论哪种方式,它都是这样工作的:

(remove-pairs '(1 (2 4) 3 5 (6 8) 7 (9 11)))
=> '(1 3 5 7)