如何使用foldr和foldl定义一个函数来反转Scheme中的列表?
我们想要的是一个简洁的解决方案,使用foldl调用反转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解决方案应该相对简单(基于我们的直觉),但折叠解决方案可能需要更多的思考.
之前与此问题相似(但记录较少)的问题最终未得到回答和/或结束.
最佳答案 这看起来像家庭作业,所以我会给你一些提示,让你开始. foldl的情况很简单,你只需要发现正确的函数来传递,并记住:foldl可以被视为向后处理列表(最后一个元素,最后一个元素),所以你要做的就是把当前的东西粘在一起具有累计值的列表中的元素:
(define (rev1 lst)
(foldl <???> lst '()))
折叠器的情况稍微有些困难,只记得foldr处理列表中的元素的顺序与它们在输入列表中出现的顺序相同.同样,您必须找到要调用的正确过程:
(define (rev2 lst)
(foldr (lambda (e a)
<???>)
lst
'()))
你需要以某种方式将e(当前元素)放在a的累计值的末尾.提示:你会发现追加和列表在这里很有用.