SICP 是不是被高估了?

大神们看这本书主要收获在哪些地方?以前看这本书的时候感觉有点被高估,一直也不敢发言,担心被喷,今天在V2EX上看到这个话题,就斗胆问一问。 希望大神们…
关注者
1,795
被浏览
616,235

41 个回答

如果是SICP的授课内容,很多人可能在看这本书之前就学过了。什么二叉树哈夫曼树啊,面向对象式编程啊,函数式编程,赋值,多线程,函数压栈等,都是司空见惯的东西了。

但是这本书上有很多的习题具有很强的现实意义,运用课本上的基本知识,来实现惊叹的应用。详情见我回答的SICP的哪些题目令人感到收获

这些只是小收获,直到现在学函数式编程和《编译原理》时,我才发现SICP传授的思想才是最令人叹为观止的。

1.系统自顶向下反复抽象,最后具体实现:

这个应该是许多人无师自通的道理。先规划出系统的蓝图,然后设想需要用到的工具,一点一点地实现,最后把轮子组合,就成了一个系统。

2.递归的精髓是闭包性质

递归是程序设计的一个常用方法,在算法中有着普遍运用。刚开始学的时候,递归是反直觉的,为什么把任务交给下一层,就能完成整体任务呢?因为递归具有闭包性质,不管是初始状态,还是下层、上层状态,它们的性质都是一样的。

首先介绍一下什么叫闭包,离散数学里闭包的解释看得人头晕,大概意思是个体一直满足一系列规则,则这些规则称之为这个个体的闭包。举个例子就很好理解:一系列数,5 乘以 7=35,4除以任何数(0除外), 1+1=2。x 运算 y = z,而且x、y、z都是实数,那么称xyz都在实数闭包内——你怎么玩都被“关”(closure)在里面。

在递归里也同理,一个整体是这个性质,它的组成部分也是这个性质,它的元素(初始状态)也是这个性质。拿树的递归来说,树是一棵树,子树也是一棵树,节点也是一颗树,因此树的递归操作可以抽象转化为性质间的操作,并通过部分的性质得到整体的性质。

3.数据类型没有什么特别的,只是按照一定的规则对数据进行存储,运算而已:

以前总是把浮点数和数据结构当做一个神秘的东西,小心翼翼地处理。但SICP教给我,只需要一些规则,然后约定俗成的使用方法,就能构造像有理数、复数的数据类型,然后我才明白浮点也是这样构造出来的。特殊数据失去了它的神秘感,一切都是抽象。

4.通用计算的本质是数据导向与消息传递

普通加法与浮点加法相差甚远,却通用一个“+”,甚至在不同的对象之间,或者像浮点2.14+整型1=浮点3.14,都能成立。我一直不明白,直到读到SICP才恍然大悟,这一切都是数据导向与消息传递而已。如何做到用一个“+”就实现所有数据类型的加法?

①把操作传入该数据类型,让数据自己决定做什么,这个在SICP叫做消息传递,但现在我们更喜欢称作“面向对象”。系统只是简单地调用不同对象内自带的计算方式而已。

②上传数据类型的一整套运算方式到系统,这个叫做数据导向。系统进行运算时,先在自己的登记表里查找对应数据类型的计算方式,再调用查找到的计算方式进行计算。有必要时甚至可以上传对应的数据转换方式,先转换数据类型,再进行两者的计算。

系统自带的数据类型一般是数据导向,而自定义的对象则一般是通过消息传递进行计算。

5.赋值是函数式编程的大忌

第一第二章用了大量篇幅讲函数式编程,但第三章却一下将前两章的美梦摧毁。两位魔法师讲赋值、副作用,函数的结果一下变得有点难以预测。看完此章后,我开始在学习函数式编程时,下意识地警惕赋值对函数式编程带来的影响。

6.变量与环境

以前学Java、Linux时,经常搞不懂类中类“闭包”,“环境变量”之类的词,觉得它们是一种很神秘的东西。在第三章中我才知道,环境就是某个阶段(如在某个函数中,某个循环中)各数据当前的定义状况。很多人说关系论的闭包和编程的闭包完全没有任何关系,但通过SICP的“环境论”,其实能猜出来为什么要把变量寻找合适的定义称之为“闭包”。关系论闭包指的是,“个体满足一系列定义的规则,则称该规则是该个体的闭包”,而编程闭包指的是“变量往上级环境寻找到自己的约束”。看起来毫无关系,但如果把变量看做个体,环境看做“一系列规则”,这样不就是一种“闭包”么?妙哉

从此每次遇到各种各样的x赋值,我总能答对x输出其中的哪个值——本质不过”变量环境论”。

7.时间是数据错乱的罪魁祸首

函数式编程,过程是固定的过程,同样的输入必然有同样的输出。而普通过程中,随着时间的流逝,各种各样的赋值带来了副作用,同样的输入可能会有不同的输出。多线程同理。在一次过程中,同样的输入会有可预测的结果;多线程中,同样的过程交错在一起,产生各种各样,难以预测的结果。这个真就很哲学了......学了那么久的操作系统,第一次有人用“时间”的视角看待多线程,而解决的思路则是“约束时间的威力”(其实就是“加锁”“多线程”“银行家算法”等,有点玄乎了)真是个大魔法师。


读了SICP后,写的Scheme程序渐渐被我遗忘,但这些编程哲学总在合适的时机浮现在我的脑海里。如果是把SICP当做一本函数式教学书、或者编译原理、组成原理入门,SICP也只是还行,但不至于成为神作,有些内容甚至过时了(第四章有一部分讲通过递归下降的方式进行自然语言处理,但机器解析翻译法已经于21世纪初被基于概率论的翻译法完全淘汰)。而SICP的编程哲学,才是让这本书登上神坛的最佳精华。

个人观点:没有高估。


我前前后后看了三遍 SICP,前两次都无疾而终,第三次花了一年半的时间把整本书看完了,习题完成率90%以上,在 [Github 上的笔记与题解](jiacai2050/sicp)也超过200 star。看完这本书,可以让你了解编程语言的本质,现如今编程语言层出不穷,Scala、Go、ES6、Swift、Rust 等等,每种语言针对的领域不一样,有的适用于系统级,有的适用于微服务,说白了都是些 DSL,只不过比较 general 而已,我们需要利用这些语言提供的语法糖来写我们的业务代码。


SICP 以 Scheme 教学,让我们可以清晰的认识到各种花哨语法糖背后的原理,有了这些基础再去学其他语言,就会显得容易许多。


当然,SICP 也有缺点,里面很多章节的内容都是电气相关知识,全书虽然只有5章,但是信息量非常大,一般人我觉得一年内看不完。