王垠:编程的宗派( 二 )


这就是为什么我喜欢开玩笑说 , 面向对象编程就像“地平说”(Flat Earth Theory) 。 当然你可以说地球是一个平面 。 对于局部的 , 小规模的现象 , 它没有问题 。 然而对于通用的 , 大规模的情况 , 它却不是自然 , 简单和直接的 。 直到今天 , 你仍然可以无止境的寻找证据 , 扭曲各种物理定律 , 自圆其说地平说的幻觉 , 然而这会让你的理论非常复杂 , 经常需要缝缝补补还难以理解 。
面向对象语言不仅有自身的根本性错误 , 而且由于面向对象语言的设计者们常常是半路出家 , 没有受到过严格的语言理论和设计训练却又自命不凡 , 所以经常搞出另外一些奇葩的东西 。 比如在JavaScript里面 , 每个函数同时又可以作为构造函数(constructor) , 所以每个函数里面都隐含了一个this变量 , 你嵌套多层对象和函数的时候就发现没法访问外层的this , 非得bind一下 。 Python的变量定义和赋值不分 , 所以你需要访问全局变量的时候得用global关键字 , 后来又发现如果要访问“中间层”的变量 , 没有办法了 , 所以又加了个nonlocal关键字 。 Ruby先后出现过四种类似lambda的东西 , 每个都有自己的怪癖…… 有些人问我为什么有些语言设计成那个样子 , 我只能说 , 很多语言设计者其实根本不知道自己在干什么!
软件领域就是喜欢制造宗派 。 “面向对象”当年就是乘火打劫 , 扯着各种幌子 , 成为了一种宗派 , 给很多人洗了脑 。 到底什么样的语言才算是“面向对象语言”?这样基本的问题至今没有确切的答案 , 足以说明所谓面向对象 , 基本都是扯淡 。 每当你指出某个OO语言X的弊端 , 就会有人跟你说 , 其实X不是“地道的”OO语言 , 你应该去看看另外一个OO语言Y 。 等你发现Y也有问题 , 有人又会让你去看Z…… 直到最后 , 他们告诉你 , 只有Smalltalk才是地道的OO语言 。 这不是很搞笑吗 , 说一个根本没人用的语言才是地道的OO语言 , 这就像在说只有死人的话才是对的 。 这就像是一群政客在踢皮球 , 推卸责任 。 等你真正看看Smalltalk才发现 , 其实面向对象语言的根本毛病就是由它而来的 , Smalltalk并不是很好的语言 。 很多人至今不知道自己所用的“面向对象语言”里面的很多优点 , 都是从过程式语言继承来的 。 每当发生函数式与面向对象式语言的口水战 , 都会有面向对象的帮众拿出这些过程式语言早就有的优点来进行反驳:“你说面向对象不好 , 看它能做这个……” 拿别人的优点撑起自己的门面 , 却看不到事物实质的优点 , 这样的辩论纯粹是鸡同鸭讲 。
函数式编程(Functional Programming)函数式语言一直以来比较低调 , 直到最近由于并发计算编程瓶颈的出现 , 以及Haskell , Scala之类语言社区的大力鼓吹 , 它忽然变成了一种宗派 。 有人盲目的相信函数式编程能够奇迹般的解决并发计算的难题 , 而看不到实质存在的 , 独立于语言的问题 。 被函数式语言洗脑的帮众 , 喜欢否定其它语言的一切 , 看低其它程序员 。 特别是有些初学编程的人 , 俨然把函数式编程当成了一天瘦二十斤的减肥神药 , 以为自己从函数式语言入手 , 就可以对经验超过他十年以上的老程序员说三道四 , 仿佛别人不用函数式语言就什么都不懂一样 。
函数式编程的优点函数式编程当然提供了它自己的价值 。 函数式编程相对于面向对象最大的价值 , 莫过于对于函数的正确理解 。 在函数式语言里面 , 函数是“一类公民”(first-class) 。 它们可以像1, 2, “hello” , true , 对象…… 之类的“值”一样 , 在任意位置诞生 , 通过变量 , 参数和数据结构传递到其它地方 , 可以在任何位置被调用 。 这些是很多过程式语言和面向对象语言做不到的事情 。 很多所谓“面向对象设计模式”(design pattern) , 都是因为面向对象语言没有first-class function , 所以导致了每个函数必须被包在一个对象里面才能传递到其它地方 。