2. 用数据构建抽象

我们现在来到了数学抽象的
关键步骤:我们忘记符号代表什么,数学家们不需要空闲,
用这些符号他能执行许多的操作,没有不得不让这些符号代表什么。
---思考的数学方式

我们在第一章中着重研究了计算流程和程序设计中的子程序的角色。
我们已经看到了如何使用原生的数据,原生的操作符,通过使用组合
条件,形式参数等如何组合子程序来形成复杂的程序,和使用定义的
方法来如何抽象程序。我们看到了一个程序能够被认为是一个流程的
当前的进化到的状态的模板,我们分类,探查,和执行了在程序中
嵌入的流程的一些公共模板的简单的算术分析。 我们也看到了高层次函数
增强了我们的语言的能力。使得我们能够操纵和理解计算的通用方法的
术语的原由。这是编程的本质的大部分的内容。

在本章中,我们要了解的是更复杂的数据。在第一章中的所有的程序都操作的是
简单的数据,简单的数据对于我们要通过计算来解决的问题的大部分来说是不足够的。
程序能够被设计来模拟复杂的现象。为了模拟有多个方面的现实世界中的现象,
我们程序中的可组装的计算对象也有几个部分。所以在第一章中,我们聚焦于通过
组合程序形成复杂的程序来进行抽象,我们在第二章中,转向到在任何一个编程
语言中的另一个重要的方面:通过组合数据对象形成复合的数据来构建抽象的方法。

在一个编程语言中为什么我们要有复合的数据对象?这与我们要有复合的程序的
原因是一样的,为了在我们设计我们的程序时提高我们的概念层次,增强我们的
设计的模块性,增强我们的语言的表达的威力。正如定义子程序的能力使我们
能在一个更高的概念层次上处理流程而不是在语言的原生操作的概念层次上。
组装复合的数据对象的能力使我们能在一个更高的概念层次上处理数据,而不是
在语言的原生的数据对象的概念层次上。

考虑一个对有理数执行算术操作的系统的设计的任务。我们想像到的是有一个操作
add-rat 取得两个有理数并生成它们的和。以简单的数字为单位,一个有理数能被认为
是由两个整数组成,一个是分子,和一个是分母。因此,我们能够设计一个程序,
在这个程序中,任何一个有理数都被表示成两个整数,一个分子,一个分母,
并且有理数的加法,能用两个方法来实现。一个计算和的分子,一个计算和的
分母。但是这是笨拙的,因为我们需要显式地追踪哪个分子对应于哪个分母。
对于一个要实现许多的有理数的许多的操作的系统来说,如此簿记员式的细节
将会明显地使程序凌乱不堪,这样做对我们的思路毫无益处。如果我们能够把
一个分子与一个分母胶合在一起,形成一对,即一个组合的数据对象,那将
大有好处,也就是我们的程序能够运行在相符于一个有理数作为一个单独的
概念单元的方式下。

组合的数的使用也能使我们增加了程序的模块性。如果我们能够把有理数作为
一个独立的对象进行操作,那么我们能够把处理有理数本身的程序的部分与
有理数作为一个整型数的数对的显示的细节 相分离开。这种 把数据对象的
显示的程序的部分从数据对象的被使用的程序的部分中隔离开来的 通用的
技术是一个强有力的设计方法,称之为数据抽象。我们将看到数据抽象是
如何使程序更容易设计,维护,和修改。

组合的数的使用使得我们的程序语言的表现力得到了无可争议的增强。
思考一个线性的表达式,ax+by.我们可以写一个程序接受a,b,x,y作为参数,
并且返回一个ax+by的结果值。如果参数是数字,这实现起来不难,因为
我们能如下地定义程序。
(define (linear-combination a b x y)(+ (* a x ) (* b y))).

但是,假定我们不仅仅只关注数字,假定我们想要表达的是用程序的方式,
生成线性表达式的思想,无论加法和乘法是为了有理数,实数,多义词或者
其他内容而定义的。我们能用如下的程序表达这种情况。
(define (linear-combination a b x y)(add (mul a x) ( mul b y)))

当add 和mul 不再是原始的+ 和* 而是更复杂的能够为我们输入的任意数据
类型的参数a,b,x,y执行适当的操作的程序。linear-combination这个程序的
关键点仅仅是它需要知道a,b,x,y这四个参数和它调用的add 和mul程序将执行
适当的操作。从linear-combination这个程序的角度看,它与a,b,x,y这几个参数
是不相关的,甚至与这几个参数是如何用元数据显示的不相关。相同的例子展示
出我们的程序语言提供直接操作组合的数据的能力是具有重要性的原因。没有了
这种能力,就不能实现只输入参数,而不了解参数的细节结构。
1。我们开始实现上面提到的有理数的算术系统。这将作为我们讨论组合数与
数据抽象的背景。对于一个结合的程序,被提出的主要议题是抽象作为一种技术
来应对复制的复杂性,并且我们将看到数据抽象是如何让我们在程序的各个部分
之间建立起适合的抽象的屏障。

我们将看到,对于生成组合的数的关键是一个编程语言需要提供一些类型的
粘合剂,它能使数据对象组合成更复杂的数据对象。这有许多类型的粘合剂。
实际上,我们将发现如何并不使用特别的数据操作仅用程序而生成组合的数。
这将更加模糊了程序和数据的区别,这已经变成接近于第一章的结尾处了。
我们也将探索一些为了表示序列和树的约定俗成的技术。处理组合数的一个
重要的思想是闭包的观念,因为我们的组合数据对象的粘合剂不仅
让我们能够粘合原始的数据,也能粘合组合的数据对象。
另一个重要的思想是组合的数据对象在混合与匹配的方式下为了组合程序
模块可以作为一致性的接口使用。通过表示一个简单的有显式的闭包的
图形语言我们说明一下这些思想的一部分。

通过介绍符号化表达式,我们将讨论我们的语言的表示能力。
数据的元素级部分能是随意的符号而不仅仅是数字。对于对象的表示集合,
我们探索不同的选择方案。我们将发现,正如一个给定的数值函数能被以多种
不同的计算过程进行计算,对于一个给定的数据结构能以简单的对象被表示
成多种方式。表示方法的选择能对操作数据的执行过程的时间和空间需求有重大的影响。
在符号微分的背景下,我们将调查这些思想,集合的表示和信息的编码。

接下来我们处理 有混合数据的问题。这种混合数据可能是随着程序的不同部分,
而被表示成不同的形式。这导致需要实现通用化的程序,它必须能处理许多不同的类型的数据。
在通用化操作的现实中,维护模块性需要更强有力的抽象隔离,而不是单独地使用简单的数据抽象。
特别地,我们包括了数据导向的编程作为一种技术,允许单独的数据被单独的设计,然后可累加性组合。
为了演示在系统设计中这种方法的威力,我们以应用了我们学习到的软件包的实现,结束了这章内容。
这个软件包执行多项式的符号算术,多项式的系数可能是整数,有理数,复数,甚至是另一个多项式。

猜你喜欢

转载自blog.csdn.net/gggwfn1982/article/details/81427763
今日推荐