现在,我已经开始尝试实施累积功能几周了。我已经正确实现了一个“Map”函数,它遍历列表并在每个元素上运行一个函数。
我正在使用此功能来实现“累积”
(define accumulate
(lambda (op base func ls)
(if(null? ls)
ls
(cond (not (null? (cdr ls)) (op base (map func ls) (accumulate op base func (cdr ls))))
(op base (map func ls) (op base (func(car ls))))
)
)))
;It gets to a point (the last element) after applying the map function to each element,
;where it is '(number) instead of an expected "number" (outside of () ). I cannot figure out
;how to circumvent this.
我坚持如何做到这一点。这样做的正确方法是什么?
预期结果是:
; accumulate: combines using OP the values of a list LS after mapping a function FUNC on it
; (accumulate + 0 sqr '(1 2 3)) => 14
; (accumulate * 1 sqr '(1 2 3)) => 36
;
答案 0 :(得分:1)
您希望实现适用于列表的折叠过程,您不需要使用map
,只需依次处理每个元素。这更像是:
(define accumulate
(lambda (op base func ls)
(if (null? ls)
base
(op (func (car ls))
(accumulate op base func (cdr ls))))))
例如:
(accumulate + 0 sqr '(1 2 3))
=> 14
(accumulate * 1 sqr '(1 2 3))
=> 36
答案 1 :(得分:1)
可 实施accumulate
map
,以获得乐趣而无利可图:
(define accumulate
(lambda (op base func ls)
(let ((z (map list ls))) ; box'em
(car (reverse ; last
(map (lambda (x y)
(let ((acc (op (car x) (func (car y)) )))
(set-car! y acc)
acc))
(reverse (cdr (reverse ; bulast
(cons (list base) z))))
z))))))
(display (accumulate + 0 (lambda(x)(* x x)) (list 1 2 3 4)))
; 0 1 2 3
; 1 2 3 4 => 30
这模拟(有明显的转折),在r5rs Scheme中,旧的懒惰流编程定义
accumulate op base ls = last z
where
z = base : zipWith op z ls -- (:) is cons
~> accumulate (+) 0 (map (^2) [1..4])
30
-- 0 a b c d +
-- 1 4 9 16 =
-- 0 a b c d
当它沿着列表移动时,它也会在一个过去当前的列表节点上“写入”累积的结果。这是例如actually known as scanl
。 Haskell,并从该列表中获取最后一个结果使其成为foldl
(左侧折叠)。