SICP 与函数式编程
马马虎虎地看完了第四章跟第五章,终于可以为 SICP 这本书画上一个句号。
似乎 GCD 跟 fibonacci 这两个程序在每门语言里都会被实现一遍。这应该是涉及到递归的定义吧,对于函数式编程来说,递归是深刻而基础的,循环可以没有,递归不可或缺。特别是 fibonacci 的双递归,一方面考验了编程使用者的技巧,另一方面考验了这门编程语言的实现。(参见 维基百科 )
其中印象比较深刻的,是将函数作为参数和返回值。而且在 scheme 的语法中,显得非常自然。C 中也有函数指针,相对地就显得复杂。
另外,就是引入表作为一种通用的数据界面进行处理了。得益于后台运行的 GC,使用表的时候不用担心自动增长的问题,可以专注于工作本身。而且,对于表的操作也只有两个原语:CAR 与 CDR。 通过这两个原语的结合,再配合前述的递归,scheme 就能发挥出它的强大威力,令人叹为观止。
数据抽象一节,很容易联想起 C 的结构体一节与 C++ 的对象,利用带标志数据,在表上实现了多样的抽象对象。后面接的就是模块化,作者煞费苦心搞出了 set!来配合讲解与 C++ 相若的对象概念,以及用计算机中的对象模拟现实世界运行的 OO 思想。那个数字电路的模拟器写得很棒,特别是约束传播,很有感觉。
数据抽象里最有力的一节,是引入流和时间解耦。流的实现居然只是简单的在 cdr 上加了一个简单的壳,用一个许诺代替了具体数据。通过引入流,作者轻松地将循环等等抛弃掉,连带的还有局部变量。对象的状态看作是一组跟时间相关的值的流,漂亮地解决了并发冲突后(实际上,时间与通信似乎有着天然的联系,参见相对论中关于火车、隧道与闪电的例子),状态就跟时间本身解耦了! 状态跟时间解耦,意味着并发性不再受到限制,这就是函数式编程天生支持高并发的原因吧。
流的另一大惊喜,是对(发生器 - 过滤器 - 累加器)这一编程模型的优化。通过流,这三者的配合可以交替执行,因此节省了中间结果所占据的巨大空间和时间。我很好奇 Linux 下的管道是否也用上了类似的优化。(流的自身迭代也很美,特别是欧拉加速器!)
第 4 和第 5 章没看懂,暂不发表意见了。以后有时间就看看 the little schemer XD