1.3.1 函数作为形式参数使用
考虑如下的三个程序:第一个计算从A到B的整数的和。
(define (sum-intergers a b)
(if (> a b)
0
(+ a (sum-intergers (+ a 1) b))))
第二个计算从给定的范围的整数的立方的和。
(define (sum-cubes a b)
(if (> a b)
0
(+ (cube a) (sum-cubes (+ a 1) b))))
第三个计算从给定的范围的整数的公式(1/a*(a+2))的和。
这个计算得到的值趋近于圆周率的八分之一。(非常慢地)
(define (sum-pi a b)
(if (> a b)
0
(+ (/ 1.0 (* a (* a 2))) (sum-pi (+ a 4) b))))
这三个程序很明显地共享一个共同的模式。它们的大部分是
相同的,不同的,仅仅是程序的名称,A的函数被用来计算
求和的通项公式,提供A的下一个值的函数。在下面的这个
通用的模板上填入占位符处的值,我们能够生成上面的三个程序
中的任何一个。
这个模板如下:
(define (<name> a b)
(if (> a b)
0
(+ (<term> a)
(<name> (<next> a) b))))
这个共同的模式的存在是一个有力的证据。就是一个有用的
抽象方法正期望着来到我们的面前。 的确,数学家们在
很久以前就标识出这个系列求和的抽象来,并且提出了
一个西歌玛的概念。
西歌玛的概念的威力在于,它允许数学家们面对这个求和的
概念本身,而不仅仅是特定的求和。
例如,关于求和的公式化的通用的结果是独立于特定的序列
被求和的。
与此相似的是,作为一个程序的设计者,我们希望我们的
编程语言有足够的表达能力,让我们能够写一个程序就能
表达求和本身的这个概念,而不仅仅是写一个程序仅能够
计算特定的求和。在编程语言中,我们能够实现上述的模板
并把代替处的值变成形式参数。
(define (sum term a next b)
(if (> a b)
0
(+ (term a)
(sum term (next a) next b))))
值得注意的是,函数sum 有形式参数 四个,是
上下边界 a b,函数 term,next.
我们能够使用函数sum 像其它的函数一样。
例如:我们能够使用它(结合一个自增的函数)来定义函数sum-cube.
(define (inc n) (+ n 1))
(define (sum-cubes a b)
(sum cube a inc b))
使用这个函数,我们能够计算从一到10的立方的和。
(sum-cubes 1 10)
3025
使用标识函数的辅助来计算通项,我们能够定义整数求和
的函数。
(define (identity x) x)
(define (sum-integers a b)
(sum identity a inc b))
然后 我们能从一加到十。
(sum-integers 1 10)
55
我们也能用同样的方式定义 pi-sum.
(define (pi-sum a b )
(define (pi-term x)
(/ 1.0 (* x (+ x 2))))
(define (pi-next x)
(+ x 4))
(sum pi-term a pi-next b))
使用这些程序,我们能够计算一个近似值(approximation)。
(* 8 (pi-sum 1 1000))
3.139592655589783
一旦我们有了sum这个函数,我们能像使用一块砖头一样
用它来公式化更多的概念。例如,a的定积分函数f 是在
a b 之间的使用公式 计算的近似值。