如何在 Scheme/Racket 中使用尾递归实现追加过程?
How to implement append procedure using tail recursion in Scheme/Racket?
很长一段时间我都在尝试使用尾递归(迭代)在 Racket 中实现追加过程。
到目前为止我做的最好的解决方案是:
(define (my-reverse lst)
(define (iter lst reversed)
(if (null? lst)
reversed
(iter (cdr lst) (cons (car lst) reversed))))
(iter lst '()))
(define (append-iter el lst)
(my-reverse (cons el (my-reverse lst))))
(append-iter 4 '(1 2 3)) ; (1 2 3 4)
我的问题是有没有更好的实现方式?
好吧,这取决于您对“更好”的定义:)。您的解决方案很简单,而且您找不到更直接的方法来编写自己的过程以使用尾递归在列表末尾追加元素。
我唯一的评论是 my-reverse
与内置的 reverse
过程相同,后者肯定是尾递归的,因此您可以简单地将其写为:
(define (append-iter el lst)
(reverse (cons el (reverse lst))))
如果你可以使用continuation passing style,下面的解决方案也是尾递归的,它只依赖于最基本的原始过程:
(define (append-iter el lst)
(append-cps lst (cons el '()) (lambda (x) x)))
(define (append-cps lst1 lst2 k)
(if (null? lst1)
(k lst2)
(append-cps
(cdr lst1)
lst2
(lambda (appended-cdr)
(k (cons (car lst1) appended-cdr))))))
无论哪种方式,它都按预期工作:
(append-iter 4 '(1 2 3))
=> '(1 2 3 4)
如果您好奇,CPS 解决方案将计算出如下所示的表达式,这自然会得出答案:
((lambda (append-cdr)
((lambda (appended-cdr)
((lambda (appended-cdr)
((lambda (x) x)
(cons 1 appended-cdr)))
(cons 2 appended-cdr)))
(cons 3 append-cdr)))
'(4))
=> '(1 2 3 4)
是的,
(define (rev-append lst reversed)
(if (null? lst)
reversed
(rev-append (cdr lst)
(cons (car lst) reversed))))
(define (append-iter el lst)
(rev-append (rev-append lst '())
(cons el '())))
略微“更好”。
rev-append
是你的 my-reverse
的 iter
。它值得拥有自己的顶级绑定。
很长一段时间我都在尝试使用尾递归(迭代)在 Racket 中实现追加过程。
到目前为止我做的最好的解决方案是:
(define (my-reverse lst)
(define (iter lst reversed)
(if (null? lst)
reversed
(iter (cdr lst) (cons (car lst) reversed))))
(iter lst '()))
(define (append-iter el lst)
(my-reverse (cons el (my-reverse lst))))
(append-iter 4 '(1 2 3)) ; (1 2 3 4)
我的问题是有没有更好的实现方式?
好吧,这取决于您对“更好”的定义:)。您的解决方案很简单,而且您找不到更直接的方法来编写自己的过程以使用尾递归在列表末尾追加元素。
我唯一的评论是 my-reverse
与内置的 reverse
过程相同,后者肯定是尾递归的,因此您可以简单地将其写为:
(define (append-iter el lst)
(reverse (cons el (reverse lst))))
如果你可以使用continuation passing style,下面的解决方案也是尾递归的,它只依赖于最基本的原始过程:
(define (append-iter el lst)
(append-cps lst (cons el '()) (lambda (x) x)))
(define (append-cps lst1 lst2 k)
(if (null? lst1)
(k lst2)
(append-cps
(cdr lst1)
lst2
(lambda (appended-cdr)
(k (cons (car lst1) appended-cdr))))))
无论哪种方式,它都按预期工作:
(append-iter 4 '(1 2 3))
=> '(1 2 3 4)
如果您好奇,CPS 解决方案将计算出如下所示的表达式,这自然会得出答案:
((lambda (append-cdr)
((lambda (appended-cdr)
((lambda (appended-cdr)
((lambda (x) x)
(cons 1 appended-cdr)))
(cons 2 appended-cdr)))
(cons 3 append-cdr)))
'(4))
=> '(1 2 3 4)
是的,
(define (rev-append lst reversed)
(if (null? lst)
reversed
(rev-append (cdr lst)
(cons (car lst) reversed))))
(define (append-iter el lst)
(rev-append (rev-append lst '())
(cons el '())))
略微“更好”。
rev-append
是你的 my-reverse
的 iter
。它值得拥有自己的顶级绑定。