如何使用foldr
和foldl
来定义一个在Scheme中反转列表的函数?
我们想要一个简洁的解决方案来使用foldl
调用和不同的foldr
调用来反转Scheme中的列表,如下所示:
(define (foldl operation lst initial)
(if (null? lst) initial
(foldl operation
(cdr lst)
(operation (car lst) initial))))
并且
(define (foldr operation lst initial)
(if (null? lst) initial
(operation
(car lst)
(foldr operation (cdr lst) initial))))
聪明的人会注意到,
foldl
实现是尾递归的,因为在每个递归步骤被调用时返回值都被计算出来了——在最后一步中,整个答案已经被计算出来并简单地返回上一级。
foldr
实现不是尾递归的,因为它必须通过使用传递回递归链的值来构建返回值。因此,我们感兴趣的两个Scheme实现应该采用以下形式,
(define (rev1 lst)
(foldl ___________________________
**Solution:**
(define (rev1 lst)
(foldl cons lst '()))
并且
(define (rev2 lst)
(foldr ___________________________
**Solution 1:**
(define (rev2 lst)
(foldr
(lambda (element accumulator)
(foldr cons accumulator (cons element '())))
lst '()))
**Solution 2:**
(define (rev2 lst)
(foldr
(lambda (element accumulator)
(append accumulator (cons element '())))
lst '()))
终极目标是能够调用以下代码:
(rev1 '(1 2 3)) -> (3 2 1)
(rev2 '(1 2 3)) -> (3 2 1)
foldl
解决方案应该相对简单(基于我们的直觉),但foldr
解决方案可能需要更多的思考。
之前类似于这个问题的问题(但文档少得多)最终没有得到答案或被关闭。