《计算机程序的构造与解释》(一)

来源:互联网 发布:mac虚拟机 360优化 编辑:程序博客网 时间:2024/05/22 10:31

    之前看过《SICP》之后写了两篇博文,介绍了过程抽象和数据抽象,主要涉及本书的第一、二、三章内容。之后,看了《The Little Scheme》,查了些其他的概念如类型系统、多态、面向对象等,自我感觉对程序的认识更上一层楼。眼中不再是C++、Java、Python、Perl等孤立的程序语法,能看到它们之间更多的共性和个性的东西,虽然对它们中任何一种都算不上熟悉或精通,那是下一步需要练习的。

    从本文开始往后一段时间,将加深对程序语言的系统认识。

程序的基本元素

    无论是functional program language还是imperative program language其组成一般包括如下机制:

  • 基本表达式,这是语言的最简单个体,由这些个体通过组合构造出复合的元素。
  • 组合的方式,描述了如何通过基本的表达式构造复合元素。
  • 抽象的方法,描述了一些特殊规则,让程序能够处理复杂的计算,并且容易理解。如给复合对象命名,让它成为操作单元。
上述三个基本机制是每个语言都必须明确规定的,并且没有歧义。通过对上述三个机制的灵活运用,程序员能够表达他们的计算思想。

    每种语言都需要定义自己的类型系统,这个类型系统表明了该语言将基本数据分为哪些类型,每个类型允许的基本操作。而组合的方式描述了如果通过基本操作过程将基本表达式组合成复合的表达式,并求值。C语言有整型、字符型、字符串、指针等等类型。以加法基本操作为例实行中缀表示法如a+b,其中a、b都是整型。而另一种语言scheme则采用的是前缀表示法(+ a b),表示加法操作。如果定义了函数func,它含有两个参数,那么在scheme语言调用函数func的方式为(func a b),a、b分别为函数func支持的实参。这样的组织方式有个好处,就是加法操作和函数func形式统一起来了,实质上加法是语言的内部函数。

    通过抽象的方法,将操作步骤和复合数据以某种合适的结构组合起来,使得编程集中在要解决的主要问题上。

变量和环境

    通过变量可以为程序的对象(数据、计算过程)起个有意义的名字,它的值就是所对应的那个对象。在定义过程变量之后,就抽象出了某种计算模式,在需要用到该模式时只要引用该变量就是对该变量表示的计算对象求值了。这样,隐去很多不必要的细节,减轻程序员的脑力负担,同时使得开发程序变得方便快捷。将值与符号关联,又能取出这些值,意味着解释器必须以某种方式维护这些对偶。这种存储被称为环境

    环境分为全局(Global)和局部(Local)环境。全局环境的意思,是它定义的变量或者过程在整个程序范围内都是有效的,变量引用时将指向唯一的对象,也即表明变量名是唯一的。在局部环境内定义的变量其作用范围只在特定环境下有效,当超出这个范围,变量的指向将不由该环境确定。不同局部环境可以定义相同的变量,指向不同的对象,在各自对应过程中引用时互补干扰。

    举个例子,给各家孩子起名字都可以叫大宝,二宝,在各自家里每个人都知道这个名字是指谁。但是到了其他地方,比如学校、广场上你再叫这个名字的时候,可能很多人有相同的名字,分不清你指的是谁。这时,需要给这个名字前面加些修饰词,比如张家、李家的大宝、二宝等等,或者起不同的名字,这样就区分开了。这是C++的namespace的实质。

组合式及复合过程的求值

    组合式与过程是交织在一起的概念。组合式由过程将子表达式组合起来,而每个子表达式又可以是组合式或者原子表达式(数值、内部操作符等)。组合的形式,是程序语言的一般语法规则。组合式构成递归定义的、有层次的树形数据结构。通过递归对这个树形结构求值,结合每个局部过程的环境,可以得到一个最上层的表达式,这个表达式的每个子表达式是些基本表达式,这个最上层的表达式的值就作为整个组合式的值。内部运算符的求值就是将它对于的操作序列作用在它的操作对象上。

    通过define特殊规则(特殊规则不同于一般的求值规则,但是同一般规则一道构成语言的语法),将一个标示符与某对象在环境中关联起来。这个对象可以是基本表达式(如数值、+、-等),也可以是表达式组合。借助形参(formal parameter)概念,复合过程可以表现出和基本过程一样的计算行为,同时隐藏了内部计算过程,程序员只需关注输入参数和返回值。定义过程时,过程将确定输入参数及其个数,称为形参。过程体内的表达式也视形参为子表达式。在过程调用时,实参将被带入函数体,实参的值将取代形参进行计算。

多路开关

    多路开关在这里其实是条件表达式的意思,实质上它起的作用就像是电路原件里的多路选择器,或者马上的岔路口,程序需要在这里做出真假判断,然后选择下面要走的路。而给出真假结果的表达式或者过程称为“谓词”。跟基本表达式和内置过程一样,程序语言也必须开天辟地的给出基本谓词,比如>、<、=、eq?以及最基本的#f和#t等。然后可以通过定义过程组合起多个操作,返回真假结果。scheme语言中两个重要的条件表达式是cond和if。if表达式可以看做是cond表达式的特例。

;以求绝对值的过程为例说明cond的语法(define (abs x)    (cond ((> x 0) x)          ((= x 0) 0)          ((< x 0) (- x))))</pre>
其一般形式为:
(cond (<p1> <e1>)      (<p2> <e2>)        ...  ...      (<pn> <en>)))

它首先包含cond符号,之后跟着若干字句,这些字句是由表达式对偶表示。对偶的第一个表达式是一个谓词,它的值将被解释为真或者假。条件表达式的求值方式:首先求值谓词p1,如果它的值为false,那就求值p2;如果p2也为false,就求值p3,直到某个谓词为真;然后对应的<e>表达式序列的值就为cond表达式的值,否则cond表达式就是未定义的。

还有一个两路开关,就是if语句。它的形式:

(if <predicate> <consequent> <alternative> )
首先计算谓词predicate,如果是真,就求值表达式<consequent>,否则求值<alternative>作为if表达式的值。

另外,除了基本谓词,还可以通过逻辑复合运算符and、or、not构造各种复合谓词。


1 0