大一上学期结束了,给我最大震撼的还是这门SICP课;由于过于震撼,我觉得有必要记录下来。原本打算学期结束后写一系列文章总结一下,不料下学期课业过于刺激,只好草草以一篇“序”结束。不过虽然课程结束了,学习仍要继续,所以学习笔记也会不断延伸(?)
说来惭愧,这学期初选课的时候,才第一次听说SICP课,后来到了正式上课,才渐渐了解。这是门名叫“计算机程序的构造和解释”的课程(Structure and Interpretation of Computer Programs/SICP),原书是MIT的著名教程,原课程是UC Berkeley的著名“网红课程”cs61a。这还是我们学校第一次引进这门课程,基本上就是使用的就是cs61a的教程,使用python作为主要的教学语言(然而秉着大一上保护萌新的原则,还是对其内容有一些删减,尽管如此,这也已经让我大开眼界)。
先看看这一学期都教了些什么吧:
- python语言
- FP部分(递归、副作用、高阶函数、lambda演算)
- 数据抽象(用函数闭包实现的树)
- OOP部分(用class重新实现数据抽象)
- scheme语言
- 解释器原理
- SQL语言
- ……
这门课的进度我是从开学震撼到结束——实在是太快了、内容太丰富了(然而即使如此,仍然比Berkeley的进度还差一大截)。照我之前的印象中,CS系入门课永远是命令式语言的,后面过渡到OOP,像FP似乎都属于先进技术了,编译原理则更是忌讳给新手打开的黑箱、魔盒……然而,我仍然做到了,完成了上面的所有内容,学到最后的同学们都做到了(确实一开课就劝退了很多“萌新”、堪称退课率最高的一门了……)。这显然是cs61a这课程设计的功劳。
CS61a
我已经吹过无数遍cs61a,因为它实在是太精致了。每一个部分显然都是经过精心设计的:
一、课程结构
课程分普通上课(Lecture)、上机实验课(Lab),作业分平时作业(Homework)和大作业(Project)。
有一说一,就作业的量来看,这个强度已经远远大于大一CS的传统基础课程“程序设计基础了(说是C++,不如说就是C编程)”。
Homework是一周一次,量不大,是与课时内容一致的练习题。值得一提的是,每次homework,都留一些附加题;这些附加题就很有深度了(似乎是课时不够塞不进,但教师真的很想传递的内容(小声)):像“匿名阶乘”(只用lambda,不递归实现阶乘,方法是不动点算子,,,)、“church numeral”(相当于让你自己发明一遍church numeral(orz))……非常震撼,都是想都不敢想会在大一接触到的内容……
重头戏是Project,感觉真的是课程设计者的心血所在了。我们这学期做了四个project,分别是:The Game of Hog(一个掷骰子游戏)、Autocorrected Typing Software(打字软件)、Ants Vs. SomeBees(Plants Vs. Zombies复刻,,,)和Scheme Interpreter(Scheme语言的解释器!!!)
纯萌新、一学期、整这四个大活儿……
当然不是从零写起……学生只负责完成核心算法(当中的几行)的实现(
我想到的一个绝佳的比喻就是IKEA的家具,,,它已经为你实现了绝大多数的工作,却硬是要你去把它自己动手安装成一个能用的家具。然而,尽管只剩下一些最微小的工作,你还是不会组装这些部件。于是,它还提供了一份非常详尽的说明书,真的手把手地教你拼成。就是看说明书、一步步地拼的过程中,竟也理解了这个家具的内部结构。而最后,你得到一个能够使用的家具,还是自己动手做成的,属实很有成就感。
回到cs61a的project,这些程序最困难的架构、UI、测试板块都已经完全提供了。另外,还附带说明书一份,整个做project的过程就是看着说明书一步步拼家具的过程。
之前总看到有人问:学C/C++这么长时间,为什么都只是“黑框程序”?为什么和看到的软件差别那么大?学这编程到底是做什么的?难道就是解数学题?
这些疑问,我肯定大部分按国内“科班编程教育”学下来的都有过。没办法,大一打基础,C++是基本功嘛。我也深知要一上来就搞图形界面显然不现实的。然而,cs61a懂学生的顾虑,在第一时间就传递给学生:编程是魔法,自己动手,什么都能创造。
不光如此,project还提供给学生阅读代码的机会,尤其是阅读优质代码的机会。这个就太难得了。据我所知,基础课“程序设计基础”就没有时间深入对代码规范的讲解——确实,比起数据类型、指针,那些“基本功”,代码风格显得不那么重要;而且,对于初学的那些几十行的小程序,也无法让学生理解为什么需要代码的规范;甚至,在上机时,为了高效a题,有种向OI/竞赛码风靠拢的倾向。
即使是OI时,阅读代码的唯一机会也就是那初赛码风奇异的阅读程序题……我还记得在我第一次看到DirectX的代码时有多震撼……
然而,cs61a的project就提供了这种“大项目”的语境,project提供的代码显然都是非常规范的,不论是命名风格还是写法,注释的量超过了有效代码。学生完成project,在填入代码前,首先要阅读;这样,就已经是“见识过好代码”的人了。
另外,project的选题也很合学生胃口啊。像讲到OOP时,就出了复刻PVZ的project,游戏物体都是一个基类派生,各种植物就是需要学生完成的各种派生类……现在,回想一下国内教科书的OOP习题……嗯,学生管理系统,,,嗯老师同学都是人,大一大二都是学生,,,
二、课程设计
以下内容均为本人学习该课程后的主观推断(
为什么选择python
一个问题就是为什么用python作为教学语言。毕竟,对CS学生来说,一上手就python的话,一些特性可能会养成不好的习惯……(之类的吧)
但就这门课来说,选择python十分合理。
首先,python是多范式的。上面提到的课程内容中,命令式的、FP、OOP都要学习,所以显然需要选择一门能够覆盖这些范式的语言。另外,python的动态解释特性(个人以为也给课程造成了一些麻烦……)使它对FP的支持比C++好了不少。
其次,python是解释执行的,支持交互式编程。为什么这点这么重要?为了课程中最吸引人的一部分:要实现一个scheme解释器。学习python,也就理解了解释的大概过程、什么是REPL。更重要的是,scheme的许多语法与python是一一对应的,这减少了完成解释器很大的一部分工作量。做完解释器,似乎只是完成了parsing,翻译成python的数据,直接就出来了。
为什么选择scheme
可能,主要原因是语法结构简单,都是前缀的表达式,便于写解释器……另外,scheme的FP也与之前所学相契合,解释的特性也与python一致,是水到渠成:scheme竟一节课学完就可以无痛感的熟练编程了,可见其课程设计的环环相扣。而,scheme的范式也与python不同,便于将两门语言对比学习。
为什么内容这么多
我的解释是目标不一样。以“程序设计基础”为代表的国内“科班编程教育”的入门课,目的就是“打好基本功”,我认为是有道理的。CS学习计算机科学,C++是最好的材料了,正如学习音乐,钢琴是最好的材料一样。但这样“埋头走路”的方式,常常会使一些(估计是大部分)学生晕头转向,不知道在学些什么,有什么意义。就像我的导师所说,他教授的编译原理课程,有很多同学一个学期下来,都不知道学的有什么用处。
而同样是作为入门课的SICP,目的却是“抬头看路”。有一说一,这样的高强度“走马观花”下来,“码力”也许确实会欠缺一些,但视野却已经大不一样了:见识到的是计算机程序设计的“蓝图”——编程是什么?程序是什么?什么是编程语言?什么是编程范式?函数式的、面向对象的,命令式的、声明式的,解决什么样的问题?什么是抽象?编程能干什么?以后还要学什么?……
这样一来,学习热情就可想而知。
三
这里还不得不提一下我们的老师,冯新宇教授。据他讲也是“临危受命”,作为编程语言方面的专家,来开这门新课。随着课程的推进,就发现和这门课的相性真的很好(逃)。毕竟要把这门内容如此丰富的课程讲明白也非易事,尤其是到编程语言的对比、特性的设计方面,编译过程的解释方面的讲解,都让我大开眼界、受益匪浅。我课下也与老师对于程序语言特性设计方面的疑惑进行了许多探讨,老师的解答都让我醍醐灌顶,使我敬仰万分……在最后一节课,老师还夹带了些“私货”,介绍了了一门更为奇异的coq语言,讲解了证明过程,还介绍了计算机程序的形式验证方法,令我叹为观止……增加了我学习Haskell的动力(?)
接下来的学习笔记,再整理SICP这门课中学到的mind-blowing的事吧(咕咕咕)。如果有空,可能还有对冯佬Q&A的番外……
- 本文作者: Frankenstein
- 本文链接: https://salty-frankenstein.github.io/blog/2019/12/06/【杂记】SICP学习笔记(序)/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!