【发布时间】:2013-11-05 01:28:15
【问题描述】:
如何使用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 解决方案可能需要更多思考。
与此问题类似(但记录较少)的先前问题最终没有得到解答和/或关闭。
【问题讨论】:
-
@JoshuaTaylor 以获取列表作为回报的方式,但不同之处在于元素的顺序不同。 OPs 对 foldl/foldr 的定义是一样的,只是首字母是最后一个参数。
-
在我看来你成功了。
-
@Sylwester Oy;我想,我在深夜发布这种方式太晚了。我不确定我在想什么。我将删除建议this answer 在这里有用的评论。