当然,你可以在不使用的情况下做到这一点iter
程序 ...
(define (add-even lista)
(cond ((null? lista) empty)
((even? (car lista)) (cons (car lista) (add-even (cdr lista))))
(else (add-even (cdr lista)))))
(add-even '(1 2 3 4 5 6 7))
; => '(2 4 6)
但我假设你用它来保持你的add-even
过程尾递归。如果是这样的话……
Your accu
可以是一个程序(而不是列表)它填补了你的“洞”cons
链。而不是返回accu
在计算结束时,您填写最后一个值,在本例中为empty
并初始化identity
反而。
I used bolding显示我更改的代码部分
(define (add-even lista)
(define (iter lista accu)
(cond ((null? lista) (accu empty))
((even? (car lista)) (iter (cdr lista)
(λ (rest) (accu (cons (car lista) rest)))))
(else (iter (cdr lista) accu))))
(iter lista identity))
(add-even '(1 2 3 4 5 6 7))
; => '(2 4 6)
所以现在你得到尾递归并按正向顺序构建列表。我鼓励您逐步进行评估,看看它是如何工作的。这是连续传球风格.
如果你稍微重命名一下变量,也许这个过程会更好
(define (add-even lista)
(define (iter l k)
(cond ((null? l) (k empty))
((even? (car l)) (iter (cdr l)
(λ (rest) (k (cons (car l) rest)))))
(else (iter (cdr l) k))))
(iter lista identity))
(add-even '(1 2 3 4 5 6 7))
; => '(2 4 6)
如果您使用的话,它会清理得更多一些named-let
(define (add-even lista)
(let iter [(l lista) (k identity)]
(cond ((null? l) (k empty))
((even? (car l)) (iter (cdr l)
(λ (rest) (k (cons (car l) rest)))))
(else (iter (cdr l) k)))))
(add-even '(1 2 3 4 5 6 7))
; => '(2 4 6)
...它甚至能清理干净more如果我们使用compose
and curry
(define (add-even lista)
(let iter [(l lista) (k identity)]
(cond ((null? l) (k empty))
((even? (car l)) (iter (cdr l) (compose k (curry cons (car l)))))
(else (iter (cdr l) k)))))
(add-even '(1 2 3 4 5 6 7))
; => '(2 4 6)