读书笔记 -- 计算机程序的构造和解释

Structure and Interpretation of Computer Programs

 

“每一位严肃的计算机科学家都应该阅读这本书。由于本书清晰,简洁和富于才智,我们强烈推荐这本书。它适合所有希望深刻理解计算机科学的人们。” —— Mitchell Wand 《美国科学家》
 
“带着崇敬和赞美,将本书献给活在计算机里的神灵。”
 
“我认为,在计算机科学中保持计算中的趣味性是特别重要的事情。这一学科在起步时饱含着趣味性。当然,那些付钱的客户们时常觉得受了骗。一段时间之后,我们开始严肃的看待他们的抱怨。我们开始感觉到,自己真的像是要负起成功的,无差错的,完美的使用这些机器的责任。我不认为我们可以做到这些。我认为我们的责任是去拓展这一领域,将其发展到新的方向,并在自己的家里保持趣味性。我希望计算机科学的领域绝不要丧失其趣味意识。最重要的是,我希望我们不要变成传道士,不要认为你是兜售圣经的人。世界上这种人已经太多了。你所知道的有关计算的东西,其他人也都能学到。绝不要认为似乎成功计算的钥匙就掌握在你的手里。你所掌握的,也是我认为并希望的,也就是智慧:那种看到这一机器比你第一次站在它面前时能做得更多的能力,这样你才能将它向前推进。”
——Alan J. Perlls (1922.4.1 - 1990.1.7)
 
 
有关于计算机程序具体是关于什么的,服务于哪类应用等等的情况常常并不重要,重要的是它们的性能如何,在用于构造更大的程序时能否与其他程序平滑衔接。程序员们必须同时追求具体部分的完美和汇合的适宜性。
 
在这部书里使用“程序设计”一词时,所关注的是程序的创建,执行和研究。
 
本书中要讨论的各种问题都牵涉到三类需要关注的对象:人的大脑,计算机程序的集合以及计算机本身。
 
每一个计算机程序都是现实中的或者精神中的某个过程的一个模型,通过人的头脑孵化出来。这些过程出现在人们的经验或者思维之中数量上数不胜数,详情琐碎繁杂,任何时候人们都只能部分地理解它们。
 
我们很少能通过自己的程序将这种过程模拟到永远令人满意的程度。正因为如此,即使我们写出的程序是一个集经过仔细雕琢的离散符号,是交织在一起的一组函数,它们也需要不断的演化:当我们对于模型的认识更深入,更扩大,更广泛时,就需要去修改程序,直至这一模型最终到达了一种亚稳定状态。而在这时,程序中就又会出现另一个需要我们去为之奋斗的模型。
 
计算机程序设计领域之令人兴奋的源泉,就在于它所引起连绵不绝的发现,在我们的头脑之中,在由程序所表达的计算机制之中,以及在由此所导致的认识爆炸之中。如果说艺术解释了我们的梦想,那么计算机就是以程序的名义执行着它们。
 
就其本身的所有能力而言,计算机是一位一丝不苟的工匠:它的程序必须正确,我们希望说的所有东西,都必须表述的准确到每一点细节。就像在其他所有使用符号的活动中一样,我们需要通过论证使自己相信程序的真。
 
大的程序是从小东西成长起来的,开发出一个标准化的程序结构的武器库,并保证其中每种结构的正确性——我们称它们为惯用法,再学会如何利用一些已经证明很有价值的组织技术,将这些结构组合成更大的结构,这些都是至关重要的。
 
本书中将详尽地讨论这些技术。理解这些技术,对于参与这种被称为程序设计的具有创造性的事业是最最本质的。特别值得提出的是,发现并掌握强有力的组织技术,将提升我们构造大型的重要程序的能力。反过来说,因为写大程序非常耗时费力,这也推动着我们去发明新方法,减轻由于大程序的功能和细节而引起的沉重负担。
 
不要问得过于频繁,以免忽略了程序设计的乐趣,使自己陷入一种喜忧参半的呆滞状态中。
 
在我们写出的程序里,有些程序执行了某个精确的数学函数(但是绝不够精确),例如排序,或者找出一系列数中的最大元,确定素数性,或者找出平方根。我们将这种程序称为算法,关于它们的最佳行为已经有了许多认识,特别是关于两个重要的参数:执行的时间和对数据存储的需求。程序员应该追求好的算法和惯用法。即使某些程序难以精确的描述,程序员也有责任去估计它们的性能,并要继续设法去改进之。
 
前言
 
我们的学生已经变成了我们的创造者。
 
一台计算机就像是一把小提琴。你可以想象一个新手试了一个音符并丢掉了它。后来他说,听起来真难听。我们已经从大众和我们的大部分计算机科学间那里反复听到这种说法。他们说,计算机程序对个别具体用途而言确实是好东西。但他们太缺乏弹性。一把小提琴或者一台打字机也同样缺乏弹性,那时你学会了如何去使用它们之前。
——Marvin Minsky
 
一个计算机语言并不仅仅是让计算机去执行操作的一种方式,更重要的,它是一种表述有关方法学的思想的新颖的形式化媒介。因此,程序必须写得能够供人们阅读,偶尔地去供计算机执行。其次,我们相信,在这一层次的课程里,最基本的材料并不是特定程序设计语言的语法,不是有效计算某种功能的巧妙算法,也不是算法的数学分析或者计算的本质基础,而是一些能够用于控制大型软件系统的智力复杂性的技术。
 
我们的目标是,使完成了这一科目的学生能对程序设计风格要素和审美观有一种很好的感觉。她们应该掌握了控制大型系统中的复杂性的主要技术。她们应该能过去读50页长的程序,只要该程序是以一种值得模仿的形式写出来的。她们应该知道在什么时候哪些东西不需要去读,哪些东西不需要去理解。她们应该很有把握地去修改一个程序,同时又能保持原来作者的精神和风格。
 
这些技能并不仅仅适用于计算机程序设计。我们所教授和提炼出来的这些技术,对于所有工程设计都是通用的。我们在适当的时候隐藏起一些细节,通过创建抽象去控制复杂性。
 
设计这门课程的基础是我们的一种信念,“计算机科学”并不是一种科学,而且其重要性也与计算机本身无太大关系。计算机革命是有关我们如何去思考的方式,以及我们如何去表达自己的思考的一个革命。在这个变化里最基本的东西,就是出现了这样一种或许最好是称为过程性认识论的现象——这就是如何从一种命令式的观点去研究知识的结构,这一观点是与经典数学领域中所采用的更具说明性的观点完全不同的。数学为精确处理“是什么”提供了一种框架,而计算则为精确处理“怎样做”的概念提供了一种框架。
 
第一章 构造过程抽象
 
心智的活动,除了尽力产生各种简单的认识之外,主要表现在如下三个方面: 1)将若干简单认识组合为一个复合认识,由此产生出各种复杂的认识。2)将两个认识放在一起对照,不管它们如何简单或者复杂,在这样做是并不将它们合而为一。由此得到有关它们的相互关系的认识。3)将有关认识与那些在实际中和它们同在的所有其他认识隔离开,这就是抽象,所有具有普遍性的认识都是这样得到的。
——John Locks 《有关人类理解的随笔》
 
真实的程序设计则需要极度细心,需要经验和智慧。软件工程大师们能组织好自己的程序,使自己能合理地确信这些程序所产生的计算过程将能完成预期的工作。他们可以事先看到自己系统的行为方式,知道如何去构造这些程序,使其中出现的意外问题不会导致灾难性的后果。而且,在发生了这种问题时,他们也能排除程序中的错误。设计良好的计算系统就像设计良好的汽车或者核反应堆一样,具有某种模块化的设计,其中的各个部分都可以独立地构造,替换,排除错误。
 
1.1 程序设计的基本元素
 
一个强有力的程序设计语言,不仅是一种指挥计算机执行任务的方式,它还应该成为一种框架,使我们能够在其中组织自己有关计算过程的思想。这样,当我们描述一个语言时,就需要将注意力特别放在这一语言所提供的,能够将简单的认识组合起来形成更复杂认识的方法方面。每一种强有力的语言都为此提供了三种机制:
  1.  基本表达形式,用于表示语言所关心的最简单的个体
  2. 组合的方法,通过它们可以从较简单的东西出发构造出复合的元素
  3. 抽象的方法,通过它们可以为复合对象命名,并将它们当作单元去操作
 
在程序设计中,我们需要处理两类要素:过程和数据(以后读者将会发现,它们实际上并不是这样严格分离的)。非形式地说,数据是一种我们希望去操作的“东西”,而过程就是有关操作这些数据的规则的描述。这样,任何强有力的程序设计语言都必须能表述基本的数据和基本的过程,还需要提供对过程和数据进行组合和抽象的方法。
 
1.1.1 表达式
前缀表示: 将运算符放在所有运算对象左边
 
1.1.2 命名和环境
程序设计语言中一个必不可少的方面,就是它需要提供一种通过名字去使用计算对象的方式。我们将名字标识符称为变量,它的值也就是它所对应的那个对象。
一般而言,计算得到的对象完全可以具有非常复杂的结构,如果每次需要使用它们时,都必须记住并重复地写出它们的细节,那将是极端不方便的事情。实际上,构造一个复杂的程序,也就是为了去一步步地创建出越来越复杂的计算性对象。
 
1.1.3 组合式的求值
解释器本身就是按照下面过程工作的:
1)求值该组合式的各个子表达式
2)将作为最左子表达式(运算符)的值的那个过程应用于相应的实际参数,所谓实际参数也就是其他子表达式的值
 
一般而言,我们应该把递归看做一种处理层次性结构的(像树这样的对象)极强有力的技术。事实上,“值向上穿行”形式的求值形式是一类更一般的计算过程的一个例子,这种计算过程称为树形积累。
 
1.1.4 复合过程
过程定义:这是一种威力更加强大的抽象技术,通过它可以为复合操作提供名字,而后就可以将这样的操作作为一个单元使用了。
 
 

转载于:https://www.cnblogs.com/lizzzzzz/p/8642864.html

你可能感兴趣的:(读书笔记 -- 计算机程序的构造和解释)