【问题标题】:Reverse a list in Scheme with foldl and foldr使用 foldl 和 foldr 反转 Scheme 中的列表
【发布时间】: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 在这里有用的评论。

标签: list scheme reverse fold


【解决方案1】:

这看起来像是家庭作业,所以我会给你一些提示来帮助你开始。 foldl 的情况很简单,您只需要找到要传递的正确函数,并记住:foldl 可以可视化为向后处理列表(最后一个元素在前,第一个元素在后),所以您所要做的就是将列表中的当前元素与累积值粘在一起:

(define (rev1 lst)
  (foldl <???> lst '()))

foldr 的情况稍微难一些,请记住foldr 处理列表中的元素的顺序与它们在输入列表中出现的顺序相同。同样,您必须找到正确的调用程序:

(define (rev2 lst)
  (foldr (lambda (e a)
           <???>)
         lst
         '()))

您需要以某种方式将e(当前元素)放在累加值a 的end。提示:你会发现append 和list 在这里很有用。

【讨论】:

  • 您使用的是 SRFI-1 的折叠,而不是 OP 提供的折叠,其中 lst 和初始值被交换。
【解决方案2】:

您的 rev1 'solution' 无法编译...如果您将 list 替换为 l 就会编译

> (define (rev1 l) 
    (foldl cons l '()))
> (rev1 '(1 2 3))
(3 2 1)

对于您的rev2,这可以作为正文:

> (foldr (lambda (a b) (append b (list a))) '(1 2 3) '())
(3 2 1)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-18
    • 1970-01-01
    相关资源
    最近更新 更多