我正在尝试编写一个函数,该函数使用给定的运算符累加值间隔并添加初始值。例如:
(accumulate-interval + 0 2 4): 2 + 3 + 4 + 0 = 9
(accumulate-interval * 1 2 5): 2 * 3 * 4 * 5 * 1 = 120
注意:只有(+)和(*)才能正常工作。
我的代码是:
(define accumulate-interval
(lambda (op init lower upper) (if (= upper lower)
(lambda (x) (op x init))
(lambda (x)
(op
((accumulate-interval op init lower (- upper 1)) x)))) ))
它返回一个过程而不是一个值。 如果你能提供帮助,我真的很感激。
答案 0 :(得分:2)
您的代码中存在一些概念性问题。我同意@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)))))
最后,将前两个帮助程序组合成问题的解决方案。请注意,在前两个解决方案中,我们完成了相同的问题分解(第一个:生成范围;第二个:累积;第三个:合并),唯一的区别是我们在这里手工编写了辅助程序,而不是使用现有的程序: / p>
(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
答案 1 :(得分:1)
它返回一个函数,因为这是你要返回的。 lambda 是一个创建匿名函数并返回对它的引用的函数。当您的代码
时(define accumulate-interval (lambda (op init lower upper) ......))
使用 lambda 创建匿名函数,返回对它的引用,并将该引用指定为 accumulate-interval 的值。因此, accumulate-interval 与该功能相关联,只要在列表中的功能位置评估 accumulate-interval ,就会运行该功能。 / p>
现在,您的累积间隔功能包含一个 if 表达式
(if (= upper lower) (lambda (x) ...) (lambda (x) ...))
因此,如果 upper 和 lower 相等,则返回对一个匿名函数的引用,否则返回另一个。这就是你告诉它要做的事情。
我不知道你在做什么,这里,但我怀疑你只是想执行你错误地包装在一个函数中并返回的代码。所以我认为你的代码看起来更像是
(if (= upper lower)
(op upper init) (op lower (accumulate-interval op init (+ lower 1) upper)))
哪个应该有用,虽然我认为你需要重新考虑你的论点,因为递归调用不在尾部位置。
考虑一下,
(if (= upper lower)
(op upper init)
(accumulate-interval (op upper init) lower (- upper 1)))
将和作为尾递归工作。
注意:我通常不会为他们做人工作业,但我认为你可能对Scheme语法有一个以上的误解,并且显示工作代码比单独和组合地探讨每个可能的误解更容易。