在上一篇博文中介绍了:
- 程序的基本元素;
- 命名与环境;
- 多路开关;
基本元素涉及基本表达式、组合式以及抽象方法,由这些能构成简单的过程,如复合数值计算。但是还不能根据不同的情况选择不同的后续操作,这就是多路开关的作用。多路开关是形象化的比喻,对应的计算机科学概念是条件表达式。条件表达式必须包含谓词表达式,根据谓词表达式的真假,执行不同的过程,这样过程的表表达力得到极大的提升。
过程的黑箱抽象化、局部化、结构化
为了求得某数的平方根,定义了(sqrt x)过程,它的输入参数x,这个过程的返回值就是x的平方根。这个过程中需要调用其他的过程,如求平方square、求下一个猜测值的过程guess等等。过程的使用者只需知道sqrt过程即可,其他的过程最好隐藏起来,作为sqrt的内部过程,对过程使用者不可见。这样就不会干扰到其他过程的命名、定义(在命名与环境小节里提到),因为这些细节与求取某数的平方根的方法相关的,而不同的方法可能会调用不同的子过程,但是这个过程的对外接口是不变的。
例如:
(define (sqrt x)
(sqrt-iter 1.0 x))
(define (sqrt-iter guess x)
(if (good-enough? guess x)
guess
(sqrt-iter (improve guess x) x)))
(define (good-enough? guess x)
(< (abs (- (square guess) x)) 0.001))
(define (improve guess x)
(average guess (/ x guess)))
上面定义了四个过程,实质上我们最关心的是sqrt过程,其他过程是作为sqrt的子过程出现的,对于sqrt的调用者来说其他三个过程是种干扰,因为不能再定义good-enough?、improve过程作为与sqrt平级的过程来使用了。当要开发一个大型程序时,每个程序员写不同的功能模块,实现不同的接口时,这个问题变得严重了。将这些子过程作为内部定义供sqrt使用就解决上述问题了。例如:
(define (sqrt x)
(define (sqrt-iter guess x)
(if (good-enough? guess x)
guess
(sqrt-iter (improve guess x) x)))
(define (good-enough? guess x)
(< (abs (- (square guess) x)) 0.001))
(define (improve guess x)
(average guess (/ x guess)))
(sqrt-iter 1.0 x))
这种嵌套定义称为块结构。