TeX China认证群组  - 讨论区

标题:转载:我和权威的故事 关于Donald Knuth和Tex

2014年02月12日 星期三 10:37

注:本文转载自yinwang的博客,并节选了其中关于Donald Knuth和Tex的部分段落,仅供大家批判。

我的观点:虽然作者略显狂妄,但我还是认同其部分观点的。我不会使用Tex,我不会去挑战Tex,我也很庆幸之前没有去挑战。

原文:

很多人(包括我)都曾经对 Knuth 和他的 The Art of Computer Programming (TAOCP) 极度崇拜。在我大学和研究生的时候,有些同学花了不少钱买回精装的 TAOCP 全三卷,说是大概不会看,但要供在书架上,镇场子。当时我本着“书非借不能读也”的原则,再加上搬家的时候书是最费力气的东西,所以坚决不买书。我就从图书馆把 TAOCP 借了来。说实话我哪里看的下去啊?那里面的程序都是用一个叫 MIX 的处理器的汇编语言写的。一个字节只有6位,每位里面可以放一个十进制数(不是二进制)!还没开始写程序呢,就开始讲数学,然后就是几十页的公式推导,证明…… 接着我就睡着了。但我总是听说有人真的看完过 TAOCP,然后就成为了大师。比尔盖茨也宣称:“要是谁看完了 TAOCP,请把简历投给我!” 在这一系列的号召和鼓吹之下,我好几次的把 TAOCP 借回来,下定决心这次一定看完这旷世奇书。每次都是雄心勃勃的开始,可从来就没看完过开头那段 MIX 机器语言和数学公式。

看不懂 TAOCP 总是感觉很失败,因为看不懂 TAOCP 就成不了“大师”,可我仍然认为 Knuth 就是计算机科学的神,总能从他那学点什么吧,所以又开始折腾他的其他作品。这就是为什么我开始用 TeX,并且成为中国 TeX 界的主要“传教士”之一。为了 TeX,我把 Knuth 的 TeXbook 借回来,从头到尾看了两遍,做完所有的习题,包括最难最刁钻的那种“double bend”习题。接着又开始看 MetaFont Book,开始使用 MetaPost 进行绘图。开头还挺有成就感,可是不多久就发现学会的那些 TeX 技巧到了临场的时候就不知道该怎么用,然后就全都忘记了。这就是为什么我把 TeXbook 看了两遍,可是看完第二遍之后不久还是忘记得一干二净。

师兄师姐看到我用 TeX,说怎么折腾这么过时的玩意儿。我很气愤他们以及国内学术界居然都用 Word 排版论文,就开始针锋相对,写出一系列煽动文章鼓吹 TeX 的种种好处,打击“所见即所得”这种低智商玩意儿。这还不够,又开始折腾 Knuth 设计的 MMIX 处理器,并且认为 MMIX 的寄存器环就是世界上最先进的设计。发现一些无关紧要的小错,就给 Knuth 发 email,居然拿到两张传说中的“Knuth 支票”,并且一度引以为豪。当然像所有拿到 Knuth 支票的人一样,你是不会去兑现它的,甚至有人把它们像奖状一样放在相框里。我还没那么疯狂,那两张支票一直在它们原来的信封里。多年以后我到美国想兑现那支票的时候,发现它们已经过期了,后来就不知道丢到哪里去了。

当你心里有了这样的权威,其他人的话你是不可能听得进去的,就算他们其实比你心目中的权威更具智慧也一样。在清华的时候我有时候去姚期智的小组听客串讲座。有一次请来了美国某大学一个教授讲算法,不知道怎么的我就跟他聊起 TAOCP,大概是想请教他如何学习算法。他跟我说 Knuth 的书已经比较过时了,你可以看看 MIT 的那本《算法导论》。可是这位教授的名气怎能和 Knuth 相比,这话我恁是没有听进去,仍然认为 TAOCP 隐藏了算法界最高的机要,永恒的珍宝。

在清华的时候我很喜欢一门叫做“计算几何”的课,就经常跟那门课的老师交流思想。有一次我在 email 里面提到 Donald Knuth 是我的偶像,那位老师很委婉的回复道:“有偶像很好啊,Knuth 也曾经是我的偶像。” 我对“曾经”这两个字感到惊讶:难道这意味着 Knuth 现在不是他的偶像了?在我执意的询问之下他才告诉我,其实世界上还有很多更聪明的人,Knuth 并不是计算机科学的一切。你应该多看看其他人的作品,特别是一些数学家的。然后他给了我几个他觉得不错的人的名字。

现在回想起来,这些话对我是有深远作用的。那位老师虽然在系里的“牛人”们眼里是个研究能力(也就是发 paper 能力)不强的人,但是他却对我的人生转折有着强有力的作用。他引导了我去追寻自己真正的兴趣,而不是去追寻虚无的名气。我发现很多人都在为着名气而进行一些自己其实不感兴趣的事情,去做一些别人觉得“牛气”的事情。我真希望他们遇到跟我一样的好老师。

在现在看来,Knuth 的 TAOCP 就是所谓的“神圣的白象”(white elephant)。大家都把它供起来,其实很少有人真的看过,却要显得好像看过一样,并且看得津津有味。这就让试图看懂它的人更加自卑和着急,甚至觉得自己智商有问题。别人都看过了,我怎么就看不懂呢?其实 TAOCP 里面的大部分算法都不是 Knuth 自己设计的,而且他对别人算法的解释经常把简单的问题搞得很复杂。再加上他执意要用汇编语言,又让程序的理解难度加倍。

有一句话说得好:“跟真正的大师学习,而不是跟他们的徒弟。”如果你真的要学一个算法,就应该直接去读那算法的发明者的论文,而不是转述过来的“二手知识”。二手的知识往往把发明者原来的动机和思路都给去掉了,只留下苍白无味,没有什么启发意义的“最后结果”。确实是这样的,多年以后当我看见 Knuth 计划中的几卷新的 TAOCP 的目录时,发现其中大部分的东西我已经通过更容易的方式学到了,因为我找到了这些知识的源头。

所以之前的那位访问清华的教授说的其实是实话,Knuth 真的落伍了,可是就算在美国也少有人知道或者承认这个情况。有一次看一个对世界上公认最厉害的一些程序员的采访,包括总所周知的一些大牛,以及 ML 的设计者 Robin Milner,Haskell 的设计者之一 Simon Peyton Jones 等人。也不知道采访者是什么心理,在对每个人的采访中他都问,你看过 TAOCP 吗?大部分人都说看过,真是了不起的巨著,很重要啊云云。只有 Robin Milner (如果我没记错的话)比较搞笑,他说我希望我看过,但是可惜实在没时间。我一直把 TAOCP 垫在我的显示器下面,这样我工作时就可以一直看着它们 :)

Knuth 说“premature optimization is the root of all evil”,然而他自己却是非常喜欢用 premature optimization 的人。他的代码里到处是莫名其妙的小聪明,小技巧。把代码弄得难懂,实际上却并没有得到很多性能的提高。有一次看 MMIX 处理器的模拟程序,发现他用来计算一个寄存器里的“1”的个数的代码非常奇怪。本来写个循环,或者用那种从末位减 1 的做法就可以了,结果他的代码用了 Programming Pearls 里面一个古怪的技巧,费了我半天时间才看懂,后来我发现这个技巧其实还不如最简单的方法。就是这些细小却又蹊跷的做法,使得 Knuth 的代码用细节掩盖了全局,所以到最后我其实也没从大体上搞懂一个处理器的模拟器应该如何工作。直到后来到 Indiana 学习了程序语言的理论之后我才发现,其实处理器模拟器(以至于处理器本身)的工作原理很简单,因为它就是一个机器代码的解释器。使用跟高级语言解释器同样的结构,你可以比较容易的写出像 MMIX 模拟器那样的东西。

Knuth 最重要的一个贡献恐怕是程序语言的 parsing (语法分析),比如 LR parsing,然而 parsing 其实是一个基本不存在的人造问题。它的存在是因为人们的误解,以为程序语言需要有跟人类语言一样的语法,所以把程序语言搞得无端的复杂和困难。如果你把语法简化一下,其实根本用不着什么 LR,LALR。我最近给我自己设计的语言写了一个 parser ,从头到尾只花了两个小时,500 行 Java 代码,包括了从 lexer 一直到 AST 数据结构的一切。完全手写的代码,根本没用任何复杂的 parsing 技术和 YACC 之类的工具,甚至正则表达式都没有用。之所以可以这样,因为我的语法设计让 parsing 极其容易,比 Lisp 还要容易。Knuth 过度的强调了 parsing。他的误导使得很多人花了几十年时间来研究 parser,到现在还在不时地提出新的技术,用于设计更加复杂的语法。何必呢?这只会让程序员和编译器都更加痛苦。如果这些人把时间都花在真正的问题上,那今天的计算机科学不知道要美好多少。

几乎每一本编译器教材都花大量篇幅来讲述 DFA, NFA, lexing, LL, LR, LALR…… 几乎每个学校的编译器课程都会花至少 30% 的时间来做 parser,折腾 LEX,YACC 等工具,而对于编译器真正重要的东西却没有得到很多的训练。这就是为什么 Kent Dybvig 的编译器课程如此有效,因为 Scheme 的语法非常简单,我们根本没有花时间来做 parser。我们的时间用在了思考真正的问题:做优化,实现尾递归,高阶函数…… 很多语言梦寐以求却又做不好的东西。这样的课程给了我可以发挥自己潜力的余地,我的课程编译器里面具有大量的独创写法,我的 X64 机器代码生成器生成极其短小的代码,让 Kent Dybvig 都在背地里琢磨是怎么回事。这些东西到现在也许仍然是世界上最先进的技术。

一个人的思维方式似乎决定了他设计的所有东西。Knuth 的另一个最重要的发明,文学编程(Literate Programming)其实也是多此一举,制造麻烦。文学编程的错误在于认为程序语言应该像人类语言,应该适应所谓的“人类思维”。然而程序语言却是在很多方面高于人类语言的,它不应该受到人类语言里的糟粕的影响。把程序按照 Knuth 的方式分开在不同的文章段落里,造成了代码之间的关系很难搞清楚,而且极其容易出错。这个错误与“Unix 哲学”的错误类似,把程序作为一行一行的文本,而不是一个像电路图一样的数据结构。我不想在这里细说这个问题,对此我专门写了一篇文章,讲述为什么文学编程不是一个好主意。

TeX 其实也是异常糟糕的设计。它过度的复杂,很少有人搞得懂怎么配置。经常为了一个简单的效果折腾很久,然后不久就忘了当时怎么做的,回头来又得重新折腾。原因就是因为 TeX 的设计缺乏一致性,特殊情况太多,而且组合(compose)能力很差。所以你需要学太多东西,而不是跟象棋一样只需要学习几个非常简单的规则,然后把它们组合起来形成无穷的变化。

在程序语言设计者看来,TeX 的语言是世界上最恶劣的设计之一,但如果没有这个语言,它也许会更加糟糕。其实 TeX 之所以有一个“扩展语言”,有一个鲜为人知的小故事。在最早的时候 Knuth 的 TeX 设计里并没有一个语言。它之所以有一个语言是因为 Scheme 的发明者 Guy Steele。Knuth 设计 TeX 的那个时候 Steele 碰巧在斯坦福实习。他听说 Knuth 要设计一个排版系统,就建议他设计一个语言,以应付以后的扩展问题。在 Steele 的强烈建议和游说之下,Knuth 采纳了这个建议。可惜的是 Steele 并没能直接参加语言的设计,在短短的一个夏天之后就离开了斯坦福。

Knuth 的作品里面有他的贡献和价值,TeX 的排版算法(而不是语言)也许仍然是不错的东西。可是如果因为这些好东西爱屋及乌,而把他所推崇的那些乱七八糟的设计当成神圣的话,那你自己的设计就逃脱不出同样的思维模式,让简单的事情变得复杂。仍然对 TeX 顶礼膜拜的人应该看一下 TeXmacs,看看它的作者是如何默默无闻的,彻彻底底的超越了 TeX 和 Knuth。

在我看来,Knuth 是个典型的精英主义者,他觉得自己做的都是最好,最有“格调”的。他利用自己的权威和特立独行来让用户屈服于自己繁复的设计,而不是想法设计出更加易用的工具。TeX 的版本号每次更新都趋近于圆周率π,意思是完美,没有 bug。他奖励大额的支票给发现 TeX 代码里 bug 的人,用于显示自己对这些代码的自信,然而他却“冰封”了 TeX 的代码,不再填加任何新东西进去,也不再简化它的设计。当然了,如果不改进代码,自然就不会出现新的 bug,然而它的设计也就因此固步自封,停留在了几十年以前。更奇怪的是,“TeX”这个词居然不按照正常的英语发音逻辑读成"teks"。每当有人把它“读错”,就有“高手”打心眼里认为你是菜鸟,然后纠正:“那个词不读 teks,而要读‘特喝’,就像希腊语里的 chi,又像是苏格兰语的 loch,德语的 ach,西班牙语的 j 和俄语的 kh。”也许这就叫做附庸风雅吧,我是纯种的欧洲人!;-) 当一个软件连名字的发音都这么别扭,这么难掌握,那这个软件用起来会怎样?每当你提到 TeX 太不直观,就有人跟你说:“TeX 是所想即所得,比你的所见即所得好多了!”可事实是这样吗?看看 TeXmacs 吧,理解一下什么是“所见即所得+所想即所得”二位一体。

我跟 Knuth 的最后一次“联系”是在我就要离开清华的时候。我从 email 告诉他我觉得中国的研究环境太浮躁了,不是做学问的好地方,想求点建议。结果他回纸信说:“可我为什么看到中国学者做出那么多杰出的研究?计算机科学不是每个人都可以做的。如果你试了这么久还不行,那说明你注定不是干这行的料。”还好,我从来没有相信他的这段话,我下定了决心要证明这是错的。多年的努力还真没有白费,今天我可以放心的说,Knuth 你错了,因为我已经在你引以为豪的多个方面超过了你。

原文出处:

http://www.yinwang.org/blog-cn/2014/01/04/authority/

如下红色区域有误,请重新填写。

    你的回复:

    请 登录 后回复。还没有在Zeuux哲思注册吗?现在 注册 !

    Zeuux © 2022

    京ICP备05028076号