您的代码中有几个概念性问题。我同意@itsbruce,向您指出正确的解决方案比修复问题中发现的每个错误更简单。
首先,请注意该过程可以根据现有的高阶函数来编写:foldr
用于累积值和build-list
创建值范围:
(define (accumulate-interval op init lower upper)
(foldr op init
(build-list (add1 (- upper lower))
(lambda (x) (+ lower x)))))
或者,在 Racket 中,您可以使用它for/list
来创建值范围:
(define (accumulate-interval op init lower upper)
(foldr op init
(for/list ([n (in-range lower (add1 upper))]) n)))
如果需要从头开始编写解决方案(可能就是这种情况),最好将问题分成几部分。首先,生成数字范围:
(define (range lower upper)
(if (> lower upper)
'()
(cons lower
(range (add1 lower) upper))))
现在,累积值:
(define (accumulate op init lst)
(if (null? lst)
init
(op (car lst)
(accumulate op init (cdr lst)))))
最后,将前面的两个辅助过程组合成一个问题的解决方案。请注意,在前两个解决方案中,我们做了完全相同的问题分解(第一个:生成范围;第二个:累积;第三个:组合),唯一的区别是这里我们手动编写了帮助程序,而不是使用已经存在的程序:
(define (accumulate-interval op init lower upper)
(accumulate op init
(range lower upper)))
当然,您可以像在您的解决方案中一样将所有过程合并为一个 - 它更有效,因为它不会创建中间数字列表:
(define (accumulate-interval op init lower upper)
(if (> lower upper)
init
(op lower
(accumulate-interval op init (add1 lower) upper))))
...但是这样做只会为一个特定问题提供量身定制的解决方案,而不是一组在其他情况下有用的可组合程序。在函数式编程风格中,最好定义通用的、可重用的函数。
无论如何,这按预期工作:
(accumulate-interval + 0 2 4)
> 9
(accumulate-interval * 1 2 5)
> 120