灯下 登录
计算机科学 / SICP / subsection 中英对照

1.3.1 Procedures as Arguments

Consider the following three procedures. The first computes the sum of the

integers from a through b:

考虑以下三个过程。第一个计算从 a 到 b 的各整数之和:

The second computes the sum of the cubes of the integers in the given range:

第二个计算给定范围内各整数的立方和:

The third computes the sum of a sequence of terms in the series

第三个计算如下级数中一系列项的和:

1

1

3

+

1

5

7

+

1

9

11

+


,

which converges to π

该级数收敛到 π

/

8 (very slowly):

8(收敛极慢):

These three procedures clearly share a common underlying pattern. They are for

the most part identical, differing only in the name of the procedure, the

function of a used to compute the term to be added, and the function

that provides the next value of a. We could generate each of the

procedures by filling in slots in the same template:

这三个过程显然共享一个共同的底层模式。它们在大多数情况下完全相同,仅在过程的名字、用于计算被加项的 a 的函数,以及提供 a 下一个值的函数上有所不同。我们可以通过在同一个模板的空槽中填入内容来生成这三个过程中的任意一个:

The presence of such a common pattern is strong evidence that there is a useful

abstraction waiting to be brought to the surface. Indeed, mathematicians long

ago identified the abstraction of

summation of a series and invented

“sigma notation,” for example

这种共同模式的存在有力地说明,有一个有价值的抽象正等待被提炼出来。事实上,数学家们很早就识别出了级数求和 (summation of a series) 这一抽象,并发明了"Σ记号",例如

n
=
a

b

f
(
n
)

=

f
(
a
)

+

+

f
(
b
)
,

to express this concept. The power of sigma notation is that it allows

mathematicians to deal with the concept of summation itself rather than only

with particular sums—for example, to formulate general results about sums

that are independent of the particular series being summed.

来表达这一概念。Σ记号的强大之处在于,它让数学家能够处理求和本身这一概念,而不仅仅是具体的某个和——例如,可以针对求和建立与所求级数无关的一般性结论。

Similarly, as program designers, we would like our language to be powerful

enough so that we can write a procedure that expresses the concept of summation

itself rather than only procedures that compute particular sums. We can do so

readily in our procedural language by taking the common template shown above

and transforming the “slots” into formal parameters:

类似地,作为程序设计者,我们希望我们的语言足够强大,使我们能够编写一个表达求和概念本身的过程,而不仅仅是计算具体某个和的过程。在我们的过程式语言中,可以很容易地做到这一点:取上面展示的公共模板,将其中的"空槽"转化为形式参数:

Notice that sum takes as its arguments the lower and upper bounds

a and b together with the procedures term and next.

We can use sum just as we would any procedure. For example, we can use

it (along with a procedure inc that increments its argument by 1) to

define sum-cubes:

注意,sum 以下界 a 和上界 b 以及过程 term 和 next 作为参数。我们可以像使用任何过程一样使用 sum。例如,我们可以用它(连同一个将参数递增 1 的过程 inc)来定义 sum-cubes:

Using this, we can compute the sum of the cubes of the integers from 1 to 10:

利用它,我们可以计算从 1 到 10 的各整数的立方和:

With the aid of an identity procedure to compute the term, we can define

sum-integers in terms of sum:

借助一个恒等过程来计算被加项,我们可以用 sum 来定义 sum-integers:

Then we can add up the integers from 1 to 10:

然后我们可以求从 1 到 10 的各整数之和:

We can also define pi-sum in the same way:

我们也可以用同样的方式定义 pi-sum:

Using these procedures, we can compute an approximation to π:

利用这些过程,我们可以计算 π 的近似值:

Once we have sum, we can use it as a building block in formulating

further concepts. For instance, the definite integral of a function f

between the limits a and b can be approximated numerically using the

formula

一旦有了 sum,我们就可以将其作为构造进一步概念的基本构件。例如,函数 f 在 a 与 b 之间的定积分可以用以下公式进行数值近似:


a
b

f

=

[

f

(
a
+

d
x

2

)

+

f

(
a
+
d
x
+

d
x

2

)

+

f

(
a
+
2
d
x
+

d
x

2

)

+

]

d
x

for small values of d

x. We can express this directly as a procedure:

当 dx 取足够小的值时。我们可以将其直接表示为一个过程:

(The exact value of the integral of cube between 0 and 1 is 1/4.)

(cube 在 0 到 1 之间的积分精确值为 1/4。)

Racket #lang sicp
(define (sum-integers a b)
 (if (> a b)
 0
 (+ a (sum-integers (+ a 1) b))))
Racket #lang sicp
(define (sum-cubes a b)
 (if (> a b)
 0
 (+ (cube a)
 (sum-cubes (+ a 1) b))))
Racket #lang sicp
(define (pi-sum a b)
 (if (> a b)
 0
 (+ (/ 1.0 (* a (+ a 2)))
 (pi-sum (+ a 4) b))))
Racket #lang sicp
(define (⟨name⟩ a b)
 (if (> a b)
 0
 (+ (⟨term⟩ a)
 (⟨name⟩ (⟨next⟩ a) b))))
Racket #lang sicp
(define (sum term a next b)
 (if (> a b)
 0
 (+ (term a)
 (sum term (next a) next b))))
Racket #lang sicp
(define (inc n) (+ n 1))

(define (sum-cubes a b)
 (sum cube a inc b))
Racket #lang sicp
(sum-cubes 1 10)
3025
Racket #lang sicp
(define (identity x) x)

(define (sum-integers a b)
 (sum identity a inc b))
Racket #lang sicp
(sum-integers 1 10)
55
Racket #lang sicp
(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))
Racket #lang sicp
(* 8 (pi-sum 1 1000))
3.139592655589783
Racket #lang sicp
(define (integral f a b dx)
 (define (add-dx x) (+ x dx))
 (* (sum f (+ a (/ dx 2.0)) add-dx b)
 dx))

(integral cube 0 1 0.01)
.24998750000000042

(integral cube 0 1 0.001)
.249999875000001