2.1.3 数据意味着什么

2.1.3 数据意味着什么

我们开始有理数的实现,在2.1.1部分,通过使用三个未特定的程序make-rat,numer,denom,
实现了add-rat,sub-rat等等.在那一点上,我们认为操作被定义在数据对象分子,分母和有理数。
它们的行为被这三个程序指定。

但是数据的准确的含义是什么呢? 说能被指定的选择子和组装子实现的东西是不充分的。
这三个程序的集合是清楚的,不是随意的。这个集合能作为一个有理数的实现的合适的基础。
我们需要保证的是,如果我们组装了一个有理数x,用整数n和d的数对,然后抽取x的分子和分母,
并且除它们,应该和n/d得到相同的结果。换句话说,对于任何整数n 和非0的整数d,如果x是
(make-rat n d),那么 (numer x)/(denom x)=n/d.

在事实上,对于有理数形成一个合适的基本的表示形式,它的唯一的条件是
make-rat,numer,denom满足上述的公式。总之,我们能认为数据能被一些选择子和组装子定义。
以及为了成为一个有效的表示方式,这些程序必须满足特定的条件。

从这个视点,能严格定义的不仅是高层次的数据对象,例如有理数,也包括低层次的对象。
考虑一下数对的概念,这是我们用来定义有理数的。我们根本没有说一个数对是什么。
仅仅是语言提供了操作数对的cons,car,cdr.但是关于这三个操作,我们仅需要知道,
如果我们要把两个对象粘在一起,就使用cons,取出其中的对象,就使用car和cdr。
也就是说,操作满足的条件是对于任何的x,y,如果z=(cons x y)那么 (car z)=x
和(cdr z)=y。的确,我们提到的这三个程序是语言中的原生程序。
然而,任何其它的满足上述条件的三个程序能被用来作为实现数对的基础。这一点被如下的
事实所展现出来。这个事实就是我们能实现cons,car,cdr仅使用程序,而不使用任何数据结构。
这是如下的定义:

(define (cons x y)
   (define (dispatch m)
         (cond ((= m 0) x)
               ((= m 1) y)
               (else (error "Argument not 0 or 1 --- cons" m))
         )
     )
   dispatch
)

(define (car z) (z 0))
(define (cdr z) (z 1))

这个程序的使用不符合我们对数据是什么的直觉。然而,我们需要做的所有的显示出
这是一种有效的表示数对的方式。验证这些程序满足上述条件。

注意到的微妙的一点是(cons x y)返回的值是一个程序。是内部定义的程序dispatch.
这个dispatch需要一个参数,返回x或者是y,依赖于参数是0或者是1。相对应的是,
(car z)被定义应用z,到0。因此,如果z是由(cons x y)形成的程序,那么z应用到0,返回x.
所以我们显示出(car (cons x y))返回x,正如预期那样。相似的,(cdr (cons x y))应用
程序1,返回y. 因此 这个数对的程序实现是一个有效的实现,如果我们存取数对,仅使用
cons,car,cdr,我们不能区别这个实现和使用真实数据结构的那样实现。

展示数对的程序化表示的要点不在于我们的语言以这种方式工作,而是它可以以这种方式工作。
(为了效率,scheme和lisp等系统直接实现数对) 。这种程序化表示,尽管有点奇怪,
但它是完美的,充分的表示数对的方式,因为它满足了数对需要满足的仅有的条件。这个例子也展示出
操作程序作为对象的能力,自动地提供了表示复合数据的能力。现在这可能似乎有一点奇特,但是数据
数据的程序化表示,在我们的编程领域中,起着核心的作用。 这种编程风格常常被叫做消息传递,
在第三章中,当我们定位模型化和模拟的问题时,我们使用它作为一个基本的工具。

练习2.4
这有一个数对的可选的程序化表示。对于这个表示,对于任何的x和y对象,验证
(car (cons xy ) 返回x.

(define (cons x y)
(lambda (m) (m x y)))
(define (car z)
(z (lambda (p q) p)))
cdr 的相应的定义是什么?(提示:为了验证这个工作,使用1.1.5部分中的替换模型)


练习2.5
如果我们要表示一个数对,2^a和3^b的乘积,其中a和b的整数,显示出我们能显示非负整数的
数对仅使用数据和算术操作。给出car,cdr,cons程序的定义。

练习2.6
在用程序表示数对的案例中,并不是特别让人难以想象。考虑一下,在一个能操作程序的语言中,
我们能够通过不使用数字(指的出非负的整数),实现0和加一的操作。
(define zero (lambda (f) (lambda (x) x)))

(define (add-1 n)
(lambda (f) (lambda (x) (f ((n f) x)))))

这种表示被叫做丘奇数,它被发明后,丘奇这个逻辑学家又发明了 来母它 演算。

直接地定义一和二,(不使用zero和 add-1)(提示使用评估(add-1 zero)的替换式子)
给出一个加法的直接的定义(而不是一个add-1的重复使用)

猜你喜欢

转载自blog.csdn.net/gggwfn1982/article/details/81427794