对于内置函数foldr
,我知道函数blueprint如下:
(foldr combine base alist)
combine
应该包含两个参数:
折叠器消耗的项目
将foldr应用于alist的其余部分的结果
我似乎无法理解如何将#2点放在参数形式中。你是怎么做到的?
combine
不是内置函数。我必须根据要求自己编写代码。
答案 0 :(得分:1)
将第二个参数视为目前的累计值。例如,如果我们要添加元素,那么acc
是所有先前ele
的总和,我们需要添加当前元素:
(foldr (lambda (ele acc) (+ ele acc))
0 ; we're adding numbers, so the base is 0
'(1 2 3 4 5))
=> 15
另一个例子 - 如果我们要复制列表,那么acc
包含列表中的前一个ele
(从最后一个开始并从那里返回)我们必须cons
1}}头部的当前元素:
(foldr (lambda (ele acc) (cons ele acc))
'() ; we're creating a list, so the base is an empty list
'(1 2 3 4 5))
=> '(1 2 3 4 5)
acc
的确切性质取决于要解决的问题,但您应该能够从前面的示例中获得想法。
答案 1 :(得分:0)
将其视为到目前为止计算的结果,foldr
从头到尾迭代,而foldl
从头到尾迭代。如果你看一个简单的实现,它会更容易看到:
(define (foldr1 f init lst)
(let r ((lst lst))
(if (null? lst)
init
(cons (f (car lst)) (r (cdr lst))))))
(foldr1 combine base '(1 2 3)) ; ==
(combine 1 (combine 2 (combine 3 base)))
(define (foldl1 f init lst)
(let r ((lst lst) (acc init))
(if (null? lst)
acc
(r (cdr lst) (f (car lst))))))
(foldl1 combine base '(1 2 3)) ; ==
(combine 3 (combine 2 (combine 1 base)))
另请注意,在某些实现中,顺序或参数会发生变化。 Racket和SRFI-1始终将累加器作为最后一个参数,但在R6RS中,fold-left
(但不是fold-right
)的参数顺序更改:
#!r6rs
(import (rnrs))
;; swap argument order
(fold-left (lambda (acc e) (cons e acc)) '() '(1 2 3))
; ==> (3 2 1)