您好、欢迎来到现金彩票网!
当前位置:2019欢乐棋牌 > 正则序 >

《计算机程序的构造和解释(SICP)》讨论的核心问题是什么?

发布时间:2019-06-24 21:22 来源:未知 编辑:admin

  “世之奇伟、瑰怪、非常之观,常在于险远,而人之所罕至焉,故非有志者不能至也。”

  前三章,前三章是个什么概念呢?大概就是为了后面的内容打基础吧!你正要步入SICP中最神奇的领域,如果你因为读完前三章“没有什么感觉”,那么就亏大发了!

  SICP公开课中文化组织者及主要译者,Learning-SICP群主,最近正以SICP书后习题为基础,发布一些小Quiz。

  部分,但并非全部。主要是模块化和黑盒抽象,计算机中两大主要基本思想。SICP关心的是:“当系统复杂度爆炸时(或者在此之前),我们如何通过有效的方法和手段去控制系统的复杂度?”

  部分,另外,如同书名说描述的那样,SICP中的“编译”都是“解释”,这种解释的行为,无外乎就是用一种机器的计算行为去模拟另一种机器。

  ”二字。SICP全书不过五章,其中有三章的标题就直接带有“抽象”这个字眼,其余两章则是暗含了“抽象”这个主题,不妨让我们来看下这五章的名称:

  (Building Abstractions with Procedures)

  (Register Machine Model of Control)

  ……其次,我们相信,在这一层次的课程里,最基本的材料并不是特定程序设计语言的语法,不是有效计算某种功能的巧妙算法,也不是算法的数学分析或者计算的本质基础,而是一些能够用于

  的主要技术……他们应该知道在什么时候哪些东西不需要去读,哪些东西不需要去理解……

  ……我们在适当的时候隐藏起一些细节,通过创建抽象去控制复杂性。我们通过建立约定的界面,以便能以一种“混合与匹配”的方式组合起一些标准的、已经很好理解的片段,去控制复杂性。我们通过建立一些新的语言去描述各种设计,每种语言强调设计中一个特定方面并降低其他方面的重要性,以

  牛顿迭代法求平方根,不但介绍了如何通过不断迭代来改进猜测,用于求取某数的平方根,这种数学意义上的

  对递归的深入讨论,纠正了我们对于递归效率低下的错误认知。实际上,尾递归优化可以使尾递归调用在常量空间内做迭代计算。(William Clinger博士在Compiler Optimization for Symbolic Languages中引征Guy Steel的话:“并不是函数调用造成压栈,是参数求值造成压栈。”)

  后,你会惊异于竟然“数据也可以是过程”。甚至你认为通过cons构造出来的序对,应该是某种数据结构,但它其实只是一个过程(见练习2.4)!

  ,为第四章创建元语言解释器打下基础。第二,由于引入了赋值,第三章额外强调黑盒化,因此可以看到很多面向对象技术的雏形,如

  上面只是粗略的概括了一下前三章的部分内容,如果你要深入挖掘,你会发现前三章蕴含了更多的财富。当你爬过了前三章,你会发现一片新的天地。如果说前三章侧重于

  有一种非常强有力的设计策略,特别适合用于构造那类模拟真实物理系统的程序,那就是基于被模拟系统的结构去设计程序的结构。对于有关的物理系统里的每个对象,我们构造起一个与之对应的计算对象;对该系统里的每种活动,我们在自己的计算系统里定义一种符号操作。采用这一策略时的希望是, 在需要针对系统中的新对象或者新活动扩充对应的计算模型时,我们能够不必 对程序做全面的修改,而只需要加入与这些对象或者动作相对应的新的符号对象。如果我们在系统的组织方面做得很成功,那么在需要添加新特征或者排除旧东西里的错误时,就只需要在系统里的一些小局部中工作。

  作者在第四章伊始就以简明而独到的语言描述了为什么我们要创建元语言抽象。在第四章中,也是SICP最为闪光熠熠的一章,显示介绍了如何用Lisp来模拟一台Lisp求值器。在这一章中,或者说就在4.1节,作者描述了如何用Scheme创建一个简易的Scheme核心解释器,一旦你了解了Scheme的求值原理,像

  等一些列听起来很“玄乎”的概念也就豁然开了了!第四章的后面扩展了Lisp的求值规则,作者把他们称作“Scheme变形”,引入了

  求值器决定了一个程序设计语言中各种表达式的意义,而它本身也不过就是另一个程序。

  ,比如用DFA通过(NFA的)子集构造去模拟NFA[谢@吕子熏兄提醒,修改了措辞]。有了这个思想,于是就有了第五章:寄存器机器里的计算。

  SICP在书中介绍了许多有趣的系统:约束传播、编译器与求值器的互联、废料收集、类型的层次系统、延时求值等。SICP是一本奇书,细细评味,你一定能发现之中的醇香。

  ✔通用教学方案是从c开始,然后分两路,一路向上讲述应用的组织,包括各种语言语法,数据库组织,网络应用,图像应用等。一路向下进入操作系统实现。

  ✔sicp教材从lisp语法开始,构成一个包含计算机理论学科的闭环系统。

  ✔闭环手法在电影中经常出现,电影的最后一个镜头和电影的第一个镜头重合,盗梦空间,星际穿越都使用了这种手法,营造了观众对电影圆性思考,无法脱离,走出电影院时从头开始思考整个电影。sicp构思也是这样,最后lisp的第五章实现说明了第一章lisp语法的由来,看完第五章后重新翻看第一章进入了新的循环

  ✔这种循环手法也可以应用在日常交流中,将谈话的结束归纳到谈话的开始,话题的参与者会陷入循环思考中。演讲,小说,电视剧,电影中经常出现这种手法

  计算机专业的核心:算法和系统。(参考Stanford的CS Core分成了Theory和System两块)。这里要提一下软件工程,软件工程是个有点像工程项目管理的科目,说SICP是在讲软件工程还是挺奇怪的。

  算法设计和分析的书挺多,流传也很广。与之对比的是,系统设计和分析没有像算法一样总结出一套系统的概念,形成一个独立的课程,大多通过操作系统、数据库、编译原理这样的课程来学习系统设计,这样Case Study的方式一方面使得计算机专业的课程量过大,另一方面使得重要的概念被淹没在具体的系统中。所以系统设计相对于算法而言,是个不太好说清楚的领域。

  SICP主要在讲的就是如何构造和分析复杂系统(程序),并提出了一套方法论:

  构造过程抽象(Building Abstractions with Procedures)

  构造数据抽象(Building Abstractions with Data)

  模块化、对象和状态(Modularity, Objects, and State)

  寄存器机器里的计算(Register Machine Model of Control)

  书中构建了很多小系统。比如第一章的计算素数、最大公因数、平方根、积分、黄金比例等,讨论了递归、迭代过程;第二章的图形语言,赫夫曼编码解码、泛型算数包,多项式计算包等,讨论了数据结构和数据类型系统;第三章实现了一个面向对象系统等;第四章实现Scheme的解释器;第五章我还没看:)。

  SICP在计算机知识领域中位置不明的问题,其实是系统设计在国内计算机课程中位置不明确导致的。系统设计入门书籍方面,感觉SICP在核心概念方面讲解是很精彩的,但在语言(scheme)、内容(实现数值计算系统、编程语言系统)、时间(最新版第二版1996年出版)方面都太非主流,所以不知道里面讲解的概念现在是否算得上主流。当前众多名校CS系统设计入门教材好像是一本叫

  Principles of Computer System Design: An Introduction

  附上我做的前两章的课后习题答案,140道题,还有别人做的答案的链接:GitHub - strint/sicpAns: 《计算机程序的构造和解释》编程题解

  SICP涉及的关于Scheme的语法比较少,刚好满足作者讲明白他想要表达的思想。所以如何想学习Scheme这一语言的话不应该看这本书。前三章一直围绕着如何设计计算机程序,层层深入又相互联系。第一章侧重于描述过程。过程的组合可以产生复合的过程。过程的抽象使得我们不用对一些过程的细节重复实现而可以直接调用过程完成我们的工作。一些过程可能共享着一套公共模式,将这种模式抽象出来,实现为高阶函数可以来表述计算的一般性过程。

  例如,当我们需要在一个程序的许多地方将一个序列中的所有数字进行求和,我们可以实现一个过程,向这个过程传入一个序列,遍历序列中的每个数字,进行求和。那么在需要的地方我们调用这个过程,而不用重复去实现。假设还有一个程序,它将一个序列中的所有素数打印出来。这两个程序都是遍历一些数据,然后对每个数进行一种操作。我们可以将这个共同模式提取出来实现为一个过程。这个过程的参数是一个序列和对每个元素执行的那个操作。我们在实现求和过程后降低了程序的复杂度,在实现高阶过程后又降低了求和过程和查找素数过程的复杂度。

  第二章主要讲解数据对象的组合,形成复合数据,以及将复合数据对象的使用与该数据对象怎么由更基本的数据对象构造起来的细节隔离开,也就是数据抽象。

  在我们实现复数的加法运算过程时,如a+ib和c+id,参数是a、b、c、d,返回的结果是a+c,b+d。的确实现了目标,但很难将过程和其用途联系起来。我们将a和c组合一起,定义为一个复数x,(car x)是实数a,(cdr x)是虚数b,这样我们传入了两个复数x、y,返回的结果是(car x)+(car y),(cdr x)+(cdr y)。这就是数据的组合。将(car x)定义为numer,将(cdr x)定义为denom。这时,我们相当于在复数的层次上进行各种操作,复数的实现被隐藏起来了,这就是数据的抽象。数据的组合和抽象使程序的可读性提高,同时降低了我们在更高的层次上构造程序的复杂度。

  拥有了过程与数据的抽象和组合技术后,我们可以较为轻松地构造更加复杂的程序。但这还不够,还需要一些组织原则,需要能够帮助我们构造起模块化的大型系统的策略。第三章介绍了一种设计策略,就是基于被模拟系统的结构去设计程序的结构。它的优势是,对任何一个模块的修改都是局部的,不需要全局代码的修改。其中一种方法是将一个大型系统看成一批对象,它们的行为可能随时间的进展而变化。每一个计算对象必须有自己的一些局部状态变量。也就是将这一世界模拟成一集相互分离的、受时间约束的、具有状态的相互交流的对象。

  看一二章时感觉编码风格就像是面向过程编码。一个系统就是由一个个抽象过程组成,而一些过程的参数可以是一个个抽象数据,然后执行一些操作,无法很好地体现数据和过程之间的关系。而看第三章的开头时,突然发现风格转变为了面对对象编程。类似C++中的类,局部状态变量就相当于类的数据成员,内部过程就相当于成员函数,同时有新增了赋值操作使数据不再是一成不变的。这种设计方法是程序更加结构化,也更加安全,更为接近真实的物理系统。而过程和数据抽象在这一个策略下仍然适用。

  另一种方法是建立流模型,可以模拟一些包含状态的系统却不需要利用赋值或变动数据。引进了一种延时求值的技术,可以看作是一种“需要驱动”的程序设 计,松开了被模拟的世界中的时间与求值中事情发生的顺序之间的紧密联系。也就是将这一世界模拟为单一的、无时间也无状态的统一体。

  两种方法有各自的优势,也有各自的短板,但作为设计策略,它们都能使我们更加接近真实的模拟系统,构造大型程序。例如,我们可以输入数据到计算器中,选择需要的操作的按钮来执行操作。那么,当只有过程与数据抽象技术:分别定义一些过程,传入数据,返回结果;对象模型:将这些过程组织成一个子系统,数据可以作为内部状态变量,计算过程将改变它们的值;流模型:将初始值和一系列需要执行的过程作为一个流,生成计算结果流。

  SICP就这样一步一步得教你如何降低构造大型程序的复杂度。但这不仅仅是介绍软件工程的书。后面两章分别从两个角度来介绍语言的实现。

  第四章主要是实现了一个元循环求值器。用Scheme来对Scheme程序进行解释。基本循环涉及语法分析,关于内部定义的部分提及扫描程序。通过维护一个环境表来实现环境模型,用来对表达式进行求值。lisp的代码即数据的思想。语法分析与执行分离优化程序执行效率。第五章则从底层的角度,介绍了Scheme的各种语法过程是如何在寄存器层次上实现的,并将Scheme翻译为一种更接近计算机硬件的语言。将存储看作变量,使我们实现了序对。废料收集是存储管理的一部分。

  四五章讲述了简单的编译原理方面的内容。由于我们是以Lisp作为教学语言进行的讲解,这种局限性也导致了涉及编译原理方面的知识较为有限。

  我们可以从软件工程和编译原理的角度看这本书。而由于作者由浅入深的讲解顺序,我们可以从第三个角度再了解一遍全书。这本书仿佛在设计一个语言。一开始我们的语言只是过程,主要用来解决一些数学问题。当数据太多,我们想要格式化得表述一些数据,体现单一数据之间的联系, 然后我们便引进了序对。现实中的数据不仅仅是数字,还有字符数据,于是引入了引号表达式。再后来的内部状态变量,流等等。第四章二三节教我们如何修改或新 增基础语言语言。我们设计了越来越多的语法,为了更好得解决我们可能会遇到的问题。为了实现它们,我们使用了正则序和应用序,后来用了环境模型。而四五章 就是讲解我们设计的语言如何在计算机上成为可能。

  用计算机解决问题:设计语言构造更加模块化的系统,编译原理完成语言的实现。这也就是这本书的书名,计算机程序的构造和解释。

  在扯回构造程序部分,作者笔下的很多实用的设计思想值得我们学习和掌握。分层设计思想将一个复杂系统通过一系列的层次构造出来,消息传递使我们将过程像类一样操作,而语法糖衣又令其表现为单纯的过程等等。这些方法都能很好得降低复杂度。此外,本书涉及的方面也比较多,很多数学方面的知识比如牛顿法,寻找不动点方法,保证概率上正确的算法,伪随机数;逻辑程序设计与数据库的实现有一定的关系;哈夫曼编码等等。

  我的看法:这本书可以给你展现一个世界,通过总结和分析可以使你对这一方面的东西有一个清晰的认识。如果读完你只是觉得是用Scheme实现一个个 程序,那你不会有大的收获。4.1节我也认为是最精彩的一部分。有人说第五章没有看的必要,应该是仁者见仁智者见智吧。我第一遍的时候第五节后面部分读得 蒙蒙懂,第二遍又是草草得读。不过我以后还要学习编译原理,可以到时候在仔细看下。但作为一本奇书,它的深度比较有限,我觉得优点过于吹捧,不过还是那句 话,每个人的看法不同。而且受我自己对计算机直到的了解的限制(学生,好多只是了解,更多的东西根本不懂),可能这本书还有一些部分我没体会到。

  读了书的前三章,我觉得核心问题就是计算机是如何描述我们真实的物理世界的,在描述的时候,又出现了什么样的问题,而我们又是怎么解决的。我梳理一下思路吧。

  我们想要用计算机程序模拟真实的物理世界,可以首先想想真实世界的特征,比如银行账户有什么特征呢?余额?账号?密码?所以,我们首先用计算机程序模拟一个银行账户,有money字段,name账号字段,password密码字段。这也就是最开始出现的数据抽象,将现实世界的数据抽象成某个字段,用于表示它的特征。就像一个杯子,我们抽象它的长length,宽width,高hight等特征,表示它。

  这种数据抽象的方法,将使一个程序中的大部分描述能与这一程序所操作的数据对象的具体表示的选择无关。就是用各种计算机存储的数据描述这个真实世界的事物。

  账户A想要转账给账户B的金额为50元,我们怎么用计算机程序去描述呢?如果能提供一种方法transfer(A,B,num),将表示为账户A转账至账户B的num金额,这是否能表述真实世界的转账操作。这一种方式也就是过程抽象,我们把真实物理世界的许多动作抽象成一个过程,比如吃抽象为eat()等方法。

  当我们把账户金额抽象为数据,转账动作抽象为过程,那么我如果想要对同一个账户两次转账呢?本来我的账户有100元,第一次转账25元剩下75元,第二次转账25元剩下还是75元吗?当然不对,应该剩下50元。所以这时又引入了新的问题,如何保存我账户的金额?

  这时我们需要维护一个状态了,就像上面例子说的我账户的金额,我需要记录下来,这个状态是随着时间的变化而变化的。将系统看作是一集带有局部状态的对象,用局部状态变量去模拟系统的状态,用对这些变量的赋值去模拟状态的变化。维护状态同时也会增加系统复杂性,引入之后,一个变量不再是简单的名字,而是索引着一个可以保存值的位置,而存储在那里的值也可以改变的。此时,还会引入环境模型,这个环境模型约束着当前环境下的实际参数,简单说就是参数在不同环境中的值可能不相同,就像控制进程上下文的PCB。

  引入状态的概念,会带来很多复杂性的问题,比如:状态需持久化,环境模型等,有没有其他方式来维护状态呢?在系统中,我们关注某个变量x随着时间的变化,试想,如果有一个函数f(x)的存在,x轴为时间,y轴为变化的趋势,随着时间的变化,y轴也随着变化。可是f(x)却没有变化,所以这个关于时间的函数没有变化,我们是不是可以理解为整个系统的流程未发生变化,这时我们引入新的数据结构————流。当我们的数据经过某个系统时,这其实就是对整个系统看作一个整体,数据会经过固定模块,最后经过系统之后就是我们想要的结果。

  第三个问题,多个用户对同一个账户进行操作,如何去描述?账户本身金额为100元,A用户存50元,B用户取130元,A用户先存和B用户先取的结果是不一样的,那么用程序描述这一动作是就需要考虑时间问题,这就是分布式问题的本质————时间。

  如何鉴别一个分布式系统是否优秀?能将高并发的并行请求的处理结果等同于串行请求的处理结果,那么本质就是按照时间发生顺序执行请求,这样就能够解决分布式中的大量数据不一致的问题。

  如何将分布式多台机器上的请求按照发生的时间顺序执行呢?这后面又应该讲讲如何分布式的各个问题了,个人觉得最核心的就是建立缓冲区,所有确定性的请求按时间顺序写入缓冲区,并顺序消费。所谓确定性是指处理过程与时间无关的,其处理结果亦不受额外输入影响。保证顺序消费,数据一致性又有了raft、paxos等一致性算法,将分布式中强一致性转换为最终一致性。

  整个计算机程序大概就是这样描述我们的真实世界的,从数据抽象到过程抽象,再赋予状态变化,模块化我们的系统,状态变化随着时间的变化而变化,时间又是分布式的本质问题。后面,我也会分享一下分布式系统处理问题上是如何保证请求的顺序性的。有什么说的不好或者不对的地方,欢迎大家指出~

  控制复杂度的能力,是区分程序员能力的最重要指标之一,而这本书就是教会你一套控制系统复杂度的方法论和理论体系。PS. 此书信息量极大,刷起来确实不轻松,要想真正学到精髓,每节后面的习题一定要做,否则就是身入金山空手而归。

  paradisms of artificial intelligence

  前三章如果把习题也写了的话,对scheme使用是比较扎实的,而且了解了一些基本的求值顺序和模型,挑着做也一样,完全不做的话跟上有点困难。

  第四章开始写一个解释器,然后添加各种特性,感觉这部分比较好玩,收获也最大。

  不同的人收获应该不太一样吧,萧大说是软件工程类的书,我看的时候更多的作为解释器入门的书,或者也可以对函数式编程增加很多认识来开阔眼界,或者看着封面上的图片发呆……

  我觉得SICP的核心问题就是,如何通过抽象的方式降低软件系统设计的复杂度。

  这本书最大的问题在于,你必须得预设你读这本书的时候什么东西都没学过……毕竟一上来就给一个连循环结构都没有的语言……

  因此,OOP或FP什么的,你必须也得预设自己从没学过,不然当他提出将数据抽象为对象时,你肯定第一反应是“这不是OOP么”,然后说这书没什么好看的……

  错了,这书最大的趣味就在这个地方,它就是在你完全不知道什么是编程范式,什么是最佳实践时,跟你讲,你应该如何通过抽象的方式去降低复杂度。这里的抽象,可以有很多方式,OOP只是其中一种。

  第一章引入了程序设计的基本元素,算法复杂度和高阶函数。第一章貌似是把函数(或者高阶函数)当做过程的抽象结果(黑箱)了。

  数据抽象的结果有很多种,数据结构、闭包函数是最简单的,我在怀疑的是那个通用性操作的系统是不是抽象类和接口的原型……

  数据抽象的方式,包括递归、组合、复合(前三个FP常用的)、继承、接口(这是OOP常用的)。

  首先分析了什么是状态,状态和赋值的关系,状态的语法模型;反正就是在给你突出状态这个东西就好了。我一开始将状态理解为作用域,毕竟纯函数和闭包函数的区别就是有无状态嘛……

  在一个拥有许多带有状态的对象系统,以及对象的变化是带有连带效果的(就是a的变化引起b的变化,b又引起c和d的变化,c又引起e)。在这样一个系统我们应该如何通过抽象的复杂度(事件订阅、消息传递和约束系统,就是Vue中的watch和computed我去……我猜尤大应该看过SICP……)

  然后,引入了并发(事件)的概念,说明了带状态的坏处。我没学过并发(毕竟我js特么是个单线程语言……),所以不知道这块怎么讲……总之感觉并发带来的问题就是读和写。解决的方案叫串行化,怎么看怎么像js的事件循环……

  最后,引出了无状态的流模式,无状态也是函数式编程的(fp)的一大特点,这种编程范式最大的特点就是不带状态,因此不会引入读写的问题;缺点么,模拟性太差……

  所以,综上所述,我觉得核心问题就是,如何通过抽象的方式来降低软件系统设计的复杂度,有哪些抽象的方式,每种抽象的方式会带来哪些优势和引入哪些问题。

  js程序员读这本书挺容易的……全是熟悉的概念……目前读3章花了5天,算上今天写总结花了6天。哦对了,这书还有个特点,在图书馆读能读到头疼,在寝室读能读嗨……

  这是一本涉及面非常广的书:从如何组织代码(软件工程)到代码的本质(计算的本质)。

  # 写在前面*斜体*表示你需要对斜体部分的含义作出细细的斟酌和思考**加粗字**表示这部分内容是被强调的,需要注意# 目的本文的目的主要在于解答以下问题:- 为什么要学习SICP?- 学习SICP的作用?- SICP讲了什么?# SICP和编程的关系(为什么要学习SICP)## 元知识和知识想要理解学习SICP和学习编程有什么样的关系?也许这样一个类比是有益理解的——学习SICP之于编程就像学习*学习*本身。让我们再具体点,当我们在讨论学习数学、学习物理时,我们的研究对象是数学和物理,当我们在讨论学习*学习*的时候,我们的研究对象不是某一具体的科目,而是*学习*本身。在其他地方,你也许见过**元知识**这样的词语,其含义表示是**关于知识的知识**,和上文讲的学习*学习*本身其实是一个意思。那么:-**元知识**和**知识(一般性知识)**的差别在哪里?- 为什么要区分这两个概念?- 学习元知识有什么好处?解答:相比于元知识,一般性知识更加专注于某一个领域,这使得一般性知识具有了某种特殊性(specialized),而元知识的关注点则更加彰显了其通用性。之所以区分这两个概念,是因为这有助于我们解答以下这个问题——**是否存在一种高效且适用于任何领域的学习方法?**或者说**是否存在这样一种知识,能够使我们更好的学习、研究其他知识**。显然,这个问题的描述就是学习元知识的好处。举个例子:*科学方法*就是一种元知识,拿物理学和经济学来说,这两门都算科学,但它们研究的对象显然都不一样,物理学更加符合我们对*科学*这个单词的认知,那么经济学为什么也算科学呢?因为它采用科学方法来研究经济。注意尽管物理学和经济学的研究对象不一样,甚至可以说大不相同(一般性知识),但是却都可以用科学方法(元知识)来研究它们。## 回到正文在讲述了知识和元知识的关系后,让我们回到SICP和编程的关系中来。学习SICP并不会教会你如何写出一个博客、论坛程序(一般性知识)。SICP的目的在于教会你,当你掌握了不论是写一个博客、还是一个论坛程序的一般性知识后,如何写出一个**好**的程序。以上是从更加笼统的角度谈述SICP这本书籍目的,接下来会再具体一点。本书的作者认为计算机科学和计算机的关系没有紧密到需要在名字中带上计算机三个字,比起说是一门科学,则更像一门艺术,并指出其真正的研究目标在于解决**如何形式化解决问题的过程?**为了理解这个目标,我们先来看看什么是***过程***?这里我们需要先区分两种知识:- 叙述性知识- 指令性知识前者告诉你是什么,后者告诉你**具体怎么去做**,而**过程就是指令性知识**。所以,再通俗的解释下,作者认为的计算机科学的目在于解决,**(在计算机中)如何以一种精确、规范性的方法来表述指令性知识**在尝试达到计算机科学的这一目标时,我们会遇到一些问题,其中最主要和重要的问题就是**当我们尝试构建非常巨大的系统时,我们如何确信这些系统是正确没有错误的**换句话说**为什么我们可以构建出非常巨大的系统,且又保证它们的正确性**,这是因为存在着**控制大型系统复杂度的技术**。而**控制大型系统复杂度的技术**就是本书要**实际**讨论的主题,本书的目的也在于教会读者掌握这些技术,所以当你疑惑SICP这本书到底再讲什么的时候,回想下这个这本书的讨论的主题,就很容易得出相应的答案了。虽说本书的主要目的在于教授控制复杂度的技术,但是本书同样教授了为掌握这些技术需要学习的基础知识,而这些基础知识恰巧也是相关领域的核心部分,这也是为什么SICP被推荐作为编程入门书的原因(不是第一本学习编程的书,而是第一本入门编程的书)。# 控制大型系统复杂度的技术相比较电气学和物理学来说,计算机科学处理的是一种理想化的组件,我们的想法和实现之间没有差距,为了理解这句话,我们来看一个例子。一个物理学家10秒钟可以撕开1张纸(这个不难),请问物理学家如何在5秒中撕开1张纸?答案很简单,只要物理学家的撕纸速度加倍就行了。那么,假设要让物理学家在1秒中撕开10张纸呢?答案依旧很简单,只要物理学家的速度变为原来的10倍就行,但我们都知道现实中是不可能的。不可能的原因就是我们理解**对于计算机科学,我们的想法和实现之间没有差距**的关键。因此,当我们尝试构建一个大型系统时,我们不会受到物理世界的约束,不需要考虑现实世界的误差、额外影响,**唯一限制我们的是我们自身大脑的思维能力**。## 三种主要技术### 黑盒抽象我们先来理解*黑盒抽象*的含义:黑盒抽象是一种有关**使用一样事物而无需了解其内部实现**的思想。如果细细思考下来,不仅于计算机科学,我们生活的世界其实就构建在这种思想之上。我们坐飞机不需要考虑飞机的实现原理,我们买车票而不必在乎是什么样的魔力使得我们可以通过一张小纸条就坐上一个呜呜叫的运输工具去往诗和远方。让我们回到计算机科学中来,来尝试思考下**为什么我们需要黑盒抽象?**上文刚才讲述了,当我们在构建大型系统时,我们受到的唯一限制就是我们大脑的思维能力。黑盒抽象可以使我们从那些实现细节中解放出来,从而有更多的精力来关注我们想要关注的事物——构建大型系统本身。其次,也有助于在大型系统中更换组件,我们依赖黑盒的功能来组织系统,而非黑盒的实现细节,对于实现同样功能的黑盒来说,我们不会因为其中一个内部实现用for语句,一个用了while语句,就无法互换这两个盒子。对于黑盒抽象来说,思考以下问题是有益的:- 用什么来构建这些盒子- 如何组合这些盒子- 如何抽象出两个盒子中的公共部分,构建出新的盒子,并且作为其他盒子的支柱- 如何找出和抽象盒子中共通的部分#### 举例让我们看看一些黑盒的例子:- 编程语言中的函数- Java中的类- 任何语言的模块机制- React、Vue框架让我们以一个简单的有关**如何找出和抽象盒子中共同的部分**的例子来结束黑盒抽象这部分内容```javascriptconst cube = x = x * x * x;const square = x = x * x;// cube和square是两个盒子,且都是对元素按次数乘以自身思想的特例// 现在我们来表述元素按次数乘以自身思想的通用形式,并将cube和square构建其之上const power = (x, n) = n === 0 ? 1 : x * power(x, n - 1);const cube = x = power(x, 3);const square = x = power(x, 2);```这是个简单的例子,一眼就可以看出共通的部分,问题在于程序的规模变大时,其共同的部分就无法一眼看出了,而SICP则讲述了如何在规模庞大的系统上找出和抽象共通的部分。### 接口约定#### 通用操作我们来考虑这样一个问题:**对于一个通用加法系统(不仅可以对数字相加,还能对相加字符串,相加多项式),如何在不影响其他相加功能的基础上,增加新的相加功能?**其解决方法就是通过约定接口,了解过JAVA的人可能知道JAVA里有接口的存在,然而要注意的是JAVA的接口只是接口约定思想的一种实现,只要符合接口约定的思想,任何语言都可以构建自己的接口机制。JavaScript在ES6中也提供了接口,任何一个实现了[Symbol.iterator]方法的对象,就可以作为let of的对象,详见[点此](docs/iterator#%E9%BB%98%E8%AE%A4-Iterator-%E6%8E%A5%E5%8F%A3)#### 大型结构和模块化何对复杂的现实世界建模并构造大型程序,有两种方法:- 面向对象编程- 函数式编程### 定义新的语言(语言抽象)当纯粹的设计已经无法控制系统复杂度时,一门新的语言也许是一个好的选择(就像Vue和React)。这里谈的新语言不是写一个python或者js出来,设计一门新语言的意图是为了强调某一个方面,并且这里谈论的新语言并非想象中的那么“重”,举个例子,以前端来说,Vue和React可以说就是两门新的语言,它们构建于JS之上,可以使用JS的语法,并且强调了某些细节(数据映射成视图,自动操作DOM结构),忽略了某些细节(手动操作DOM结构,人脑同步各种状态)。其中Vue也许比React更像一门新的语言(前者多了一些DSL,后者的JSX只是语法糖),但其中的思想是一样的。# 如何掌握所有的编程语言虽然讲述编程语言不是SICP的主要目标,但是本书还是在这方面提供了不少有益的帮助SICP提供了一种**通用的编程语言模型**,即任何一门语言都要关注以下三点:- 基本元素- 组合的方法:如何组合基本元素构成复合的元素- 抽象的方法:- 如何把基本元素组合,封成**黑盒**- 如何使用这些盒子- 如何标识和找到这些盒子- 如何把这些盒子同样当作基本元素进行组合和抽象因为教授如何掌握编程语言不是SICP的主要目标,尽管提供了相应的帮助,但没有详细的发展,王垠的博客里详细的扩充了这一段内容,[见此](7/07/06/master-pl)。

  ①基本过程(过程是将输入转化为输出的一组活动,经过抽象(命名,说明使用方法)后即是函数,可以认为过程包括运算符和函数):基本代数运算,基本逻辑运算,基本控制结构等(控制结构也可以看做是一个过程,因为它接受某种输入然后产生某种输出,比如选择结构接受某个过程的布尔值,然后输出某个过程。循环结构接受某个循环条件,然后输出跳转指令,但lisp中只有迭代,没有循环)

  ②组合数据的手段:将多个数据组合成一个数据结构。在提供组合数据的手段的同时提供选择数据结构中某个数据的过程。

  ①对组合后形成的组合体进行命名,从而能够在使用时忽略其内部组成细节来直接使用。(命名应该反映其功能,即自然语言中已有的概念,比如平方根、求最大值、数组、表等,命名的好坏反映了对某个复合过程或者数据结构的理解)

  ②对组合体的使用方法,比如某个复合过程的输入和输出是什么、输入输出的关系是什么,功能是什么。数据结构如何使用,如何使用相关函数对其进行处理等。

  以第一人称用过程对数据进行处理。适用于步骤明确的问题,比如数学问题(牛顿法求平方根,微分方程的数值算法等)。

  赋予数据属性和行为从而形成对象,以第三人称指挥对象。适用于对实体建模的问题,比如第三章的电路构造是对一个层次性的系统进行建模。

http://aedelfrith.com/zhengzexu/66.html
锟斤拷锟斤拷锟斤拷QQ微锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷微锟斤拷
关于我们|联系我们|版权声明|网站地图|
Copyright © 2002-2019 现金彩票 版权所有