在Scheme中使用foldl实现功能foldr

时间:2018-10-20 05:00:55

标签: functional-programming scheme racket

foldr(向右折叠)基本上是按照存储在列表中的值从右到左的顺序执行递归计算。 foldlfoldr相反。我想知道人们是否可以使用foldr实现功能foldl?任何想法表示赞赏,在此先感谢。

2 个答案:

答案 0 :(得分:3)

  

我想知道人们是否可以使用foldr来实现功能foldl ...

foldl从左到右遍历该列表一次-它也是尾部递归的

(define (foldl f acc xs)
  (if (null? xs)
      acc
      (foldl f
             (f acc (car xs))
             (cdr xs))))

foldr遍历列表一次,将对f的调用堆积到列表的最后一个元素–不是尾递归

(define (foldr f acc xs)
  (if (null? xs)
      acc
      (f (foldr f acc (cdr xs))
         (car xs))))

我们在下面验证其输出–

(foldl list 'init '(a b c))
;; '(((init a) b) c)

(foldr list 'init '(a b c))
;; '(((init c) b) a)

可以肯定,您可以使用foldrreverse来实现foldl,但这将遍历输入列表两次。每张折叠存在的原因是,您可以在任一方向上处理列表,而不必遍历一次...

答案 1 :(得分:0)

解决方案

在将所有参数传递给foldl之前,只需反转输入列表:

(define (myfoldr func init-val lst)
  (foldl func init-val (reverse lst)))

测试

第一:

(foldr (lambda (el acc) (list el acc))
       '()
       '(1 2 3 4 5))

;; => '(1 (2 (3 (4 (5 ())))))

(foldl (lambda (el acc) (list el acc))
       '()
       '(1 2 3 4 5))

;; => '(5 (4 (3 (2 (1 ())))))

现在:

(myfoldr (lambda (el acc) (list el acc))
         '()
         '(1 2 3 4 5))

;; => '(1 (2 (3 (4 (5 ())))))

foldlfoldr

(define (myfoldl func initial-val lst)
  (foldr func init-val (reverse lst)))

测试:

(myfoldl (lambda (el acc) (list el acc))
         '()
         '(1 2 3 4 5))

;; => '(5 (4 (3 (2 (1 ())))))