如何使用抽象列表函数(foldr
,foldl
,map
和filter
)编写函数,而不使用消耗数字列表的递归{{1并生成交替的和(list a1 a2 a3 ...)
?
答案 0 :(得分:8)
这是一个提示:
a1 - a2 + a3 - a4 ... aN
与
相同a1 - (a2 - (a3 - (a4 - ... (aN - 0) ...)))
现在如何解决它是否明显?
答案 1 :(得分:1)
这是一个可能的解决方案:
(define (sum-abstract-list-functions lst)
(car
(foldl
(lambda (e acc)
(cons (+ (car acc) (* e (cdr acc)))
(- (cdr acc))))
'(0 . 1)
lst)))
我只使用foldl
,cons
,car
,cdr
。诀窍?累加两个值:实际总和(在累加器的car
部分中)和当前符号(累加器的cdr
部分中的+/- 1)。累加器初始化为0表示总和,+1表示符号,最后我返回总和,即累加器的car
部分。像这样使用它:
(sum-abstract-list-functions (list 1 2 3 4 5))
> 3
编辑:
正如已经指出的,这个解决方案是最简单的:
(define (sum-abstract-list-functions lst)
(foldr - 0 lst))
答案 2 :(得分:1)
这是家庭作业吗?好吧,我们可以将这个问题分成两个子问题:
(a1 a2 a3 a4 ... a2n-1 a2n)
列表并交替否定其中的元素,以生成(a1 (- a2) a3 (- a4) ... a2n-1 (- a2n))
。第二部分是微不足道的:
(define (sum xs)
(foldl + 0 xs))
第一个是更难的,但它并不太难。您需要转换列表,同时保持一个布尔状态,指示您是在检查偶数元素还是奇数元素,并相应地否定。我可以看到三种方法:
map
的闭包中。闭包然后从一次调用到下一次调用修改其环境。这是第三种方法的一个例子(如果这是用于家庭作业,我打赌你的老师可能不相信你想出来了):
(define (contextual-foldr compute-next
compute-init
advance-context
left-context
xs)
(if (null? xs)
(compute-rightmost-result left-context)
(compute-next left-context
(car xs)
(contextual-foldr compute-next
compute-init
advance-context
(advance-context (car xs) left-context)
(cdr xs)))))
(define (contextual-map contextual-fn advance-context left-context xs)
(contextual-foldr (lambda (left elem rest)
(cons (fn left elem) rest))
'()
advance-context
left-context
xs))
(define (alternate-negations xs)
(contextual-map (lambda (negate? elem)
(if negate?
(- elem)
elem))
not
#f
xs))