SICP 的第一章初步介绍了与函数(procedure)相关的抽象。
抽象就是站在一个更高层次上看待问题。在较高的层次上的抽象,可以表达较低层次上一些相同的模式。
我们上小学的时候,刚开始学一些算术,都是一些具体的问题:
2 * 3 = 6
3 * 4 = 12
后来,我们又学习了代数,代数表达的就是更抽象的概念,例如下面的等式可以表达所有的乘法关系。
a * b = c
这个代数式在更高层次上进行抽象,表达了较低层次上的相同模式。
在程序设计上其实也是一样。我们设计出一个函数,这个函数表达的是一些计算模式,这些计算模式独立于函数的参数的变化。
刚开始的时候,是一些基本的抽象,表达一个简单的计算过程,参数就是数字:
(define (cube x)
(* x x x))
cube 是对三次方计算过程的抽象,无论任何数字,都可以用这个计算过程来抽象。
随后,介绍了高阶函数(Higher-Order Procudures),这类函数可以把函数本身当作参数或者返回值。是函数之上的函数。
之前说过,抽象是把一些固定的模式抽取出来,在计算过程中,有些是变化的,有些是不变的,不变的成为固定的模式,而变化的成为参数。 在高阶函数中,变化部分不仅仅是简单的数字,还可以是计算过程本身。
下面几个计算过程
1 + 2 + ... + 100
1^2 + 2^2 + ... + 1000^2
1/2 + 2/2 + ... + 999/2
不变的计算模式就是计算一系列数的和,变的地方是起始点和终止点,以及 对每一项的计算方式。所以,我们可以让计算一系列数的和这一不变的计算模式 成为一个函数,将起始点,终止点,计算每一项的方式,三个元素变成参数,由此得到一个高阶函数:
(define (sum term a b)
(if (> a b)
0
(+ (term a)
(sum term (+ 1 a) b))))
其中 term 就是每一项的计算模式。
抽象可以避免重复,因为把一些固定模式抽取出来了,就可以避免重复表达这种固定模式。另外,抽象可以让我们避免处理过多的低层次细节, 保持表达上的简洁,同一抽象层次处理的东西少,可以让我们集中精力思考这一层次上的事情,把这层的事情处理好。
抽象需要对计算过程进行观察,看哪些计算模式是固定的,哪些是经常变化的。另外,也不是越抽象越好,SICP 中说,经验丰富的程序设计者 可以知道做出什么程度的抽象是合适的。我们经常听到对 Java 程序的抱怨,说他们嵌套了一层又一层,用了一个设计模式又一个设计模式, 这些程序,大概就是做了过度的抽象吧。
原文地址:http://blog.csdn.net/on_1y/article/details/42929439