【发布时间】:2018-10-21 13:25:30
【问题描述】:
foldr (fold-right) 基本上是递归计算以存储在列表中的值的从右到左的顺序执行。而foldl 是foldr 的反面。我想知道人们可以使用foldl 实现函数foldr 吗?任何想法都值得赞赏,在此先感谢。
【问题讨论】:
标签: functional-programming scheme racket
foldr (fold-right) 基本上是递归计算以存储在列表中的值的从右到左的顺序执行。而foldl 是foldr 的反面。我想知道人们可以使用foldl 实现函数foldr 吗?任何想法都值得赞赏,在此先感谢。
【问题讨论】:
标签: functional-programming scheme racket
我想知道人们是否可以使用
foldl实现函数foldr...
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)
当然,您可以使用reverse 和foldl 实现foldr,但这会遍历输入列表两次。每个折叠存在的原因是您可以在任一方向处理列表而无需多次遍历它...
【讨论】:
解决方案
在将所有参数传递给 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 ())))))
【讨论】:
(reverse lst) 是 (foldl cons '() lst)