程序语言与……

程序语言的设计类似于其它很多东西的设计。有些微妙的地方只有用过更好的设计的人才能明白。现在我就简要介绍一下我自己的体会。

程序语言与微波炉

很多人都想减肥,就像很多人都想学会编程。姑且不说一味的减肥好不好,现在只谈一下什么是有效的减肥方法。

我自己也有一段时间很胖,也有减肥的经历,而且非常成功。如果有一天我不小心又变胖了,我有非常科学而可靠的办法减回去。我的方法就是一句话:让每天吃进去的热量比消耗的少一些,但是不至于难受,另外适当运动来增加热量的消耗。很显然嘛,根据热力学定律,每天消耗的能量比摄入的多,多出来的部分只能通过分解你身上的物质(脂肪)来产生。我的减肥方法就像某些程序语言教会我的编程理念,是不随潮流而改变的真理。它让我的程序不管用什么语言写都优美而精悍。

我不是自私的人,我希望大家都健康一点,养眼一点。我已经轻易地告诉了你减肥的终极真理,一分钱都不收,可是你不相信我。你觉得肯定没那么简单,或者你觉得那样太辛苦,自己不可能照办。这就像很多人对编程的希望:要是我不学编程也能编程该多好啊!

很多程序语言就是针对这群人而产生的,它们大部分的工作花在了研究人的心理和做广告上面。它们就像电视广告里铺天盖地的减肥药:不需运动,不用节食,一个星期瘦 20 斤!它们提出各种新的术语,什么减肥茶,片,胶囊,螺旋,燃脂,纤维,宫廷,祖传,秘方,各种生化术语…… 再加上一些 PS 出来的前后效果对比图,你痛快地花不菲的价钱买了这药,然后每天好几次的像做化学实验一样精确的按时按量服用。这时候任何人跟你说这药不灵的话你都不会相信,你觉得这些人都是想跟你争夺异性的目光故意想让你继续胖下去而其实她(他)们自己背地里也吃这药,所以你对此减肥药必胜的信心有增无减。

当然你不会成功。在持续服用好多个月,甚至好几年之后,你按照广告里说的“无效退款”条例要求退款。可是减肥药公司说,是你自己没有按说明书服用,或者你吃药之前肯定比现在还胖很多。你拿不出证据,后悔当初没到公证处开你当时体重的证明。可是你仍然相信,世界上一定会有真正有效的减肥药。你觉得国内的公司喜欢骗人,所以你到了美国,寻找传说中那世界一流的减肥药……

程序语言与棋

一条这样的特殊规则就够伤脑筋了,据我所知国际象棋还有至少其它两条类似的规则。它们跟其他的规则组合在一起的时候就产生了组合爆炸效应,你发现每走一步,甚至貌似无关的动作都得检查它们是否会出现。你不得不随时把这么复杂的规则放在脑子里。没事找事也不要找这么麻烦的事啊。

这些规则就像是要你记住 C 语言里的 ++i+i++ 或者 if (x = “foo”) {…} 是什么意思。经过多年的痛苦经历之后,你多希望不再需要理解这样的代码。可是一旦这样的规则被加到语言里面,总会有人为了显示自己的水平和记忆力去用它们。不得已,你只好陪他们玩。

如果你觉得多了这些无厘头的规则会让国际象棋比中国象棋难度大或者更加有趣,那你就低估了中国象棋了。中国象棋的“游戏树复杂度”其实比国际象棋还要高,高达 10150,而国际象棋只有 10123。这跟中国象棋的棋盘要稍微大点有关系,但是总比记忆那些麻烦的规则好多了。所以相对来说中国象棋既简单又耐玩。

如果国际象棋还凑合算是简单的话,大部分的程序语言就像是魔鬼棋,飞行棋,或者三国杀。它们几乎完全由类似的特殊规则构成。哇,那么多的人物,道具和特殊技,好玩!可是会玩象棋或者国际象棋的人都会觉得它们无聊透顶。

那么是不是规则越简单越少的棋越好呢棋就比中国象棋还简单,那么围棋是不是更好玩呢觉得不是的。围棋对我来说太慢,太单调,棋盘太大,耗时太多,而且胜负居然不能一眼就看出来,要数好一会儿!这哪里是在玩,纯粹就是在做组合优化题嘛。我觉得这种任务适合交给电脑去做。所以其实简单也有一个界限,超过了这个界限对于人就没有很大区别了,反而会开始感觉缺少一些东西。

我觉得中国象棋和围棋一样简单,它的规则虽然比围棋多,但是仍然处于人脑容易记忆的范围,而且每条规则都很直接了当,没有很隐晦的条件。中国象棋的长距离武器(车和炮)让它比围棋多了很多乐趣,而对于象,马和王的走法的限制,让它比起国际象棋多了几分安心和舒适。国际象棋的后,两个车,两个相的攻击距离和范围太大,让人觉得眼睛很辛苦,因为每一个位置都可能被从太多个方向远距离攻击。而那个王,由于可以到处乱跑,以至于你感觉不是在抓一个住在戒备森严的城堡里的人,而是一只在野外乱跑的老鼠。

什么游戏会让人觉得有趣,真是一个值得研究的问题。我觉得象棋和我以前推荐过的一个游戏 Braid 里面含有同一种吸引人的设计:屈指可数但又有足够变化的简单规则,组合起来制造出许许多多的变化。这种特征其实也是鉴别一个优秀的程序语言的标准。

程序语言与音乐

前段时间 AK-47 的设计者 Kalashnikov 去世的时候,我从一篇文章了解到他设计 AK-47 的故事,发现 AK 跟我喜欢的程序语言设计有异曲同工之妙。

AK 简单得就像一把锤子。它身上没有太空时代的材料。大多数汽车修理店都有可以制造出 AK 的工具。

这篇文章首先提到,AK 的高可靠性最主要来自于它的简单,而其实简单也是程序语言最重要的东西。程序员需要解决的问题一般都挺复杂,如果他们的工具再被设计得复杂,那么他们大量的脑力就被浪费在解决这语言的问题,而不是真正需要解决的问题了。

Kalashnikov 开始的时候把任何有可能出问题的设计都排除在外了。

与简单的设计背道而驰,现在很多程序语言为了赶潮流或者吸引眼球,喜欢标新立异,喜欢加入很多“特性”,可是这些特性很有可能不但不解决问题,而且会制造问题。绝大部分程序员都不理解这个道理,所以有些人听说我在设计自己的语言就问我:“它有什么新特性吗我没法回答他们,因为我的设计几乎没有新的特性。我现在所做的一切思考和试验都是在去掉不必要的麻烦。一个语言缺少一些好的特性,以后还可以加进去,可是它如果多了一些问题特性,那一旦有人开始用就没法去掉了。

AK 上面没有袖珍和娇气的部件。这样你就不用费事在草丛里,泥地上或者溪流里找它们了。

士兵是人,会摔跤犯错误,程序员也是人,所以程序员的武器应该像士兵的武器一样,方便他们找到问题。可是很多程序语言让程序员犯错误之后花很多时间和精力才能找到错误的所在,浪费大量本来可以用来解决问题的时间。我的前同事 TJ 说他刚进入博士学习的时候花了好几个月,就为了找到 C 代码里面一个指针计算错误,导致内存结构破坏和莫名其妙的错误结果,而出现指针计算错误的位置跟错误结果出现的位置毫无关系。我也遇到过类似的问题。C 语言的指针不就像是某些武器上面的袖珍部件吗不小心掉在地上就找不到了。

AK 只有一个复杂一点的部件,那就是它的弹夹。弹夹的设计很大程度上影响到枪的整体性能,所以 Kalashnikov 在上面花了很多设计时间。

程序语言与……

这个工程经验其实对于程序语言的设计者有启发意义,因为弹夹与枪主体的接口,和程序语言的函数接口很类似。Tony Hoare 在他的《给程序语言设计的建议》中也提到,函数的调用必须简单而且快速,因为调用的开销会累积起来形成很大的性能问题。可惜的是很多语言没有注意到这个问题,函数调用时总是有一堆的动态检查和重载要做,很大程度的影响了它们的性能。

AK 的美,在于它身上没有部件具有不必要的精确性。

这对于程序语言或者编程来说也是有启发意义的。有些人为了所谓的程序“正确性”,损害了它的简单性。他们的代码异常复杂,而且喜欢写很多测试,让自己感觉对程序的“质量”有个底。然而这其实是自欺欺人。这些测试不但不能保证程序的正确,它们阻碍了程序员对程序进行彻底性的修改,防止了他们看到更加简单,甚至一眼就知道是正确的解决方案。

程序语言的设计也是。有些语言(特别是所谓 dependent type 的语言)想达到程序的完全正确,加入了很多很多的限制条件,要求程序员写很多的辅助声明甚至机器证明。结果很简单一个问题都需要很长的代码才能写出来,这些辅助的逻辑代码严重的影响了程序的阅读和转换。而且由于数理逻辑本身的局限性,它们经常迫使程序员的思路绕弯子。其实起到了相反的结果,让他们看不到更简单的方法。

Kalashnikov 不是天才,他不是为了发明而发明,他解决不了问题的时候就高兴地从别人那里学过来。

这是非常值得我们程序语言设计者学习的。很多程序语言专家都有盲目排斥“对手”的心理,“自己人”的东西就不假思索的表扬,对手的东西就一味的批评。最后的结果是没有把敌人的好东西学过来,让自己人吃亏。在操作系统和数据库等领域也有类似的思维方式,这是非常有害的。

直到被更好的东西取代,AK 会继续和我们在一起。什么才是“更好”,这是由历史和民族来定义的,而不是枪支设计专家。

在计算机的世界里也是一样,程序语言,操作系统,数据库…… 它们的好坏不应该是由它们的设计者决定的,而是看它们是否经得起时间的考验。很多几十年前以为是好的设计,到现在已经很明显的显示出了它们的缺点。这就是为什么我喜欢批评一些语言,操作系统和数据库的设计,因为我看到了它们在历史的长河中已经快要到达终点。自欺欺人的掩盖这些缺陷只会让我们输掉战争。

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2015年11月13日
下一篇 2015年11月14日

相关推荐