【问题标题】:Reverse a list in Scheme with foldl and foldr使用 foldl 和 foldr 反转 Scheme 中的列表
【发布时间】:2013-11-05 01:28:15
【问题描述】:

如何使用foldrfoldl 在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(当前元素)放在累加值aend。提示:你会发现appendlist 在这里很有用。

【讨论】:

  • 您使用的是 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
    相关资源
    最近更新 更多