使用给定运算符累积值间隔

时间:2012-10-16 14:53:58

标签: scheme

我正在尝试编写一个函数,该函数使用给定的运算符累加值间隔并添加初始值。例如:

(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))))     ))

它返回一个过程而不是一个值。 如果你能提供帮助,我真的很感激。

2 个答案:

答案 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语法有一个以上的误解,并且显示工作代码比单独和组合地探讨每个可能的误解更容易。