Loading...

超越平均水平

Original

2001年4月,修订于2003年4月

(本文源自2001年弗朗茨开发者研讨会上发表的演讲。)

在1995年夏天,我的朋友罗伯特·莫里斯和我创办了一家名为 Viaweb的初创公司。 我们的计划是编写软件,让最终用户能够建立在线商店。 当时,这款软件的新颖之处在于它运行在我们的服务器上,使用普通的网页作为界面。

当然,很多人可能在同一时间有这个想法,但据我所知,Viaweb是第一个基于网络的应用程序。对我们来说,这似乎是一个如此新颖的想法,以至于我们以此命名公司:Viaweb,因为我们的软件通过网络工作,而不是在你的桌面计算机上运行。

这款软件的另一个不寻常之处在于,它主要是用一种叫做Lisp的编程语言编写的。它是第一个用Lisp编写的大型最终用户应用程序之一,而在此之前,Lisp主要用于大学和研究实验室。[1]

秘密武器

埃里克·雷蒙德写过一篇名为《如何成为黑客》的文章,其中他告诉有志成为黑客的人应该学习哪些语言。他建议从Python和Java开始,因为它们易于学习。严肃的黑客还应该学习C,以便破解Unix,以及Perl用于系统管理和cgi脚本。最后,真正严肃的黑客应该考虑学习Lisp:

学习Lisp是值得的,因为当你最终理解它时,你将获得深刻的启蒙体验;这种体验将使你在余生中成为更好的程序员,即使你实际上并不常用Lisp。

这与学习拉丁语时常听到的论点是一样的。它不会让你找到工作,除非你成为一名古典学教授,但它会提高你的思维能力,使你在想要使用的语言(如英语)中成为更好的写作者。

但等一下。这个比喻并没有那么远。拉丁语不会让你找到工作的原因是没有人说拉丁语。如果你用拉丁语写作,没有人能理解你。但Lisp是一种计算机语言,计算机会说你,程序员,告诉它的任何语言。

所以如果Lisp让你成为更好的程序员,正如他说的那样,为什么你不想使用它呢?如果一位画家被提供了一支能让他成为更好画家的画笔,我认为他会想在所有的画作中使用它,不是吗?我并不是想嘲笑埃里克·雷蒙德。总体而言,他的建议是好的。他关于Lisp的说法几乎是传统智慧。但传统智慧中存在矛盾:Lisp会让你成为更好的程序员,但你却不会使用它。

为什么呢?毕竟,编程语言只是工具。如果Lisp确实能产生更好的程序,你应该使用它。如果不能,那谁还需要它呢?

这不仅仅是一个理论问题。软件是一个竞争非常激烈的行业,容易形成自然垄断。编写软件更快、更好的一家公司,在其他条件相同的情况下,会将其竞争对手挤出市场。当你创办一家初创公司时,你会非常敏锐地感受到这一点。初创公司往往是全有或全无的提案。你要么变得富有,要么一无所有。在初创公司中,如果你押错了技术,你的竞争对手将会压垮你。

罗伯特和我都很熟悉Lisp,我们看不出有什么理由不相信我们的直觉,选择Lisp。我们知道其他人都在用C++或Perl编写他们的软件。但我们也知道这并不意味着什么。如果你以那种方式选择技术,你就会在运行Windows。当你选择技术时,你必须忽略其他人正在做什么,只考虑什么是最有效的。

在初创公司中,这一点尤其重要。在大公司中,你可以做所有其他大公司正在做的事情。但初创公司不能做所有其他初创公司所做的事情。我认为很多人甚至在初创公司中也没有意识到这一点。

平均大公司的年增长率约为10%。所以如果你经营一家大公司,并且以平均大公司的方式做所有事情,你可以期待与平均大公司一样的表现——也就是每年增长约10%。

当然,如果你经营一家初创公司,情况也是如此。如果你以平均初创公司的方式做所有事情,你应该期待平均表现。这里的问题是,平均表现意味着你将会倒闭。初创公司的生存率远低于50%。所以如果你经营一家初创公司,你最好做一些不同寻常的事情。如果不这样,你就会陷入麻烦。

在1995年,我们知道一些我认为我们的竞争对手不理解的事情,甚至现在也很少有人理解:当你编写的软件只需在自己的服务器上运行时,你可以使用任何你想要的语言。当你编写桌面软件时,强烈倾向于使用与操作系统相同的语言编写应用程序。十年前,编写应用程序意味着用C编写应用程序。但对于基于Web的软件,特别是当你拥有语言和操作系统的源代码时,你可以使用任何你想要的语言。

然而,这种新自由是一把双刃剑。现在你可以使用任何语言,你必须考虑使用哪种语言。试图假装没有变化的公司冒着发现竞争对手并没有这样做的风险。

如果你可以使用任何语言,你会使用哪种?我们选择了Lisp。 首先,很明显,在这个市场上快速开发将是重要的。我们都是从零开始,因此能够在竞争对手之前完成新功能的公司将具有巨大的优势。我们知道Lisp是一个非常适合快速编写软件的语言,而基于服务器的应用程序放大了快速开发的效果,因为你可以在软件完成的那一刻发布它。

如果其他公司不想使用Lisp,那就更好了。这可能会给我们带来技术优势,而我们需要所有的帮助。我们开始Viaweb时,没有商业经验。我们对市场营销、招聘、筹集资金或获取客户一无所知。我们俩甚至从未有过可以称之为真正工作的工作。我们唯一擅长的就是编写软件。我们希望这能拯救我们。我们在软件方面获得的任何优势,我们都会抓住。

所以你可以说使用Lisp是一次实验。我们的假设是,如果我们用Lisp编写软件,我们将能够比竞争对手更快地完成功能,并且在我们的软件中做一些他们无法做到的事情。由于Lisp是如此高级,我们不需要一个庞大的开发团队,因此我们的成本会更低。如果真是这样,我们可以以更少的钱提供更好的产品,并且仍然盈利。我们最终会获得所有用户,而我们的竞争对手将一无所获,最终倒闭。无论如何,这是我们希望发生的事情。

这个实验的结果是什么?有些令人惊讶的是,它成功了。我们最终有许多竞争对手,大约二十到三十个,但他们的软件没有一个能与我们的竞争。我们有一个在服务器上运行的所见即所得在线商店构建器,感觉就像一个桌面应用程序。我们的竞争对手只有cgi脚本。我们在功能上总是远远领先于他们。有时,竞争对手绝望地试图引入我们没有的功能。但由于Lisp我们的开发周期如此之快,以至于有时我们可以在竞争对手在新闻发布会上宣布新功能后的两天内复制出一个新功能。当负责新闻发布会的记者打电话给我们时,我们也会有新功能。

我们的竞争对手一定觉得我们有某种秘密武器——我们在解码他们的恩尼格玛通信或其他什么。事实上,我们确实有一个秘密武器,但它比他们意识到的要简单。没有人向我们泄露他们功能的消息。我们只是能够比任何人想象的更快地开发软件。

当我大约九岁时,我偶然得到了弗雷德里克·福赛斯的《杰卡尔日》。主角是一个被雇来杀死法国总统的刺客。刺客必须越过警察,进入一个俯瞰总统路线的公寓。他打扮成一个拄着拐杖的老人,走过他们身边,他们从未怀疑他。

我们的秘密武器类似。我们用一种奇怪的人工智能语言编写软件,语法奇特,充满了括号。多年来,听到人们以这种方式描述Lisp让我感到恼火。但现在这对我们有利。在商业中,没有什么比你竞争对手不理解的技术优势更有价值。在商业中,正如在战争中,出其不意的效果与力量同样重要。

所以,我有点尴尬地说,在我们为Viaweb工作期间,我从未公开谈论过Lisp。我们从未向媒体提及它,如果你在我们的网站上搜索Lisp,你只会找到我简历中两本书的标题。这并不是偶然。初创公司应该尽量少给竞争对手提供信息。如果他们不知道我们的软件是用什么语言编写的,或者不在乎,我希望保持这种状态。[2]

最了解我们技术的人是客户。他们也不在乎Viaweb是用什么语言编写的,但他们注意到它运行得非常好。它让他们在几分钟内建立出色的在线商店。因此,主要通过口碑,我们获得了越来越多的用户。到1996年底,我们在线上大约有70家商店。到1997年底,我们有500家。六个月后,当雅虎收购我们时,我们有1070个用户。今天,作为雅虎商店,这款软件继续主导其市场。它是雅虎最有利可图的产品之一,使用它构建的商店是雅虎购物的基础。我在1999年离开了雅虎,所以我不知道他们现在有多少用户,但我最后听说大约有20,000个。

布鲁布悖论

Lisp有什么好处?如果Lisp如此优秀,为什么没有人使用它?这些听起来像是修辞性问题,但实际上它们有直接的答案。Lisp之所以优秀,不是因为某种只有信徒才能看到的魔力,而是因为它是现有的最强大的语言。而每个人不使用它的原因是,编程语言不仅仅是技术,还是思维习惯,而思维习惯的变化是最慢的。当然,这两个答案都需要解释。

我将以一个令人震惊的有争议的声明开始:编程语言在能力上是有差异的。

几乎没有人会争辩,至少高级语言比机器语言更强大。今天大多数程序员会同意,通常你不想用机器语言编程。相反,你应该用高级语言编程,并让编译器为你将其翻译成机器语言。这个想法甚至已经内置于硬件中:自1980年代以来,指令集是为编译器而不是人类程序员设计的。

每个人都知道用机器语言手动编写整个程序是个错误。更少有人理解的是,这里有一个更普遍的原则:如果你有几种语言可供选择,其他条件相同,编程时选择最强大的语言是错误的。[3]

这个规则有许多例外。如果你正在编写一个必须与用某种语言编写的程序紧密配合的程序,可能最好用同一种语言编写新程序。如果你正在编写一个只需做一些非常简单的事情的程序,比如数字运算或位操作,你可以使用一种不那么抽象的语言,尤其是因为它可能稍微快一些。如果你正在编写一个短小的、一次性的程序,你可能最好使用具有最佳库函数的语言。但一般来说,对于应用软件,你希望使用最强大的(合理高效的)语言,使用其他语言是一个错误,性质上与用机器语言编程是一样的,尽管可能程度较轻。

你可以看到机器语言是非常低级的。但至少作为一种社会惯例,高级语言通常被视为等同的。它们并不是。技术上,“高级语言”这个术语并没有什么明确的含义。没有一条明确的界限将机器语言与所有高级语言分开。语言沿着一个抽象度的连续体[4]分布,从最强大的语言一直到机器语言,而机器语言本身的能力也各不相同。

考虑Cobol。Cobol是一种高级语言,因为它被编译成机器语言。有人会认真争辩Cobol的能力与Python相当吗?它可能更接近机器语言而不是Python。

或者Perl 4呢?在Perl 4和Perl 5之间,语言中添加了词法闭包。大多数Perl黑客会同意Perl 5比Perl 4更强大。但一旦你承认这一点,你就承认了一种高级语言可以比另一种更强大。由此不可避免地得出结论,除非在特殊情况下,你应该使用最强大的语言。

然而,这个想法很少被推向结论。在某个年龄之后,程序员很少自愿切换语言。无论人们习惯于使用哪种语言,他们往往认为这已经足够好。

程序员对他们喜欢的语言非常依恋,我不想伤害任何人的感情,因此为了说明这一点,我将使用一种假设的语言,称为Blub。Blub恰好位于抽象度连续体的中间。它不是最强大的语言,但比Cobol或机器语言更强大。

事实上,我们假设的Blub程序员不会使用它们中的任何一种。当然,他不会用机器语言编程。这就是编译器的作用。至于Cobol,他不知道任何人如何能用它完成任何事情。它甚至没有x(你选择的Blub特性)。

只要我们的假设Blub程序员在向下看能力连续体,他知道自己在向下看。比Blub更弱的语言显然更弱,因为它们缺少他习惯的某些特性。但当我们的假设Blub程序员向上看能力连续体时,他并没有意识到自己在向上看。他所看到的只是奇怪的语言。他可能认为它们的能力与Blub大致相当,但还混入了其他一些复杂的东西。Blub对他来说已经足够好了,因为他用Blub思考。

然而,当我们转向使用任何更高能力语言的程序员的观点时,我们发现他反过来又看不起Blub。你怎么能在Blub中完成任何事情?它甚至没有y。

通过归纳法,唯一能够看到各种语言之间能力差异的程序员是那些理解最强大语言的人。(这可能就是埃里克·雷蒙德所说的Lisp让你成为更好的程序员的意思。)你不能相信其他人的观点,因为布鲁布悖论:他们对自己所使用的任何语言都感到满意,因为它决定了他们对程序的思考方式。

我从自己的经历中知道这一点,作为一个高中生用Basic编写程序。那种语言甚至不支持递归。很难想象在不使用递归的情况下编写程序,但当时我并不觉得缺失。我用Basic思考。而且我在这方面很出色。是我所看到的一切的主人。

埃里克·雷蒙德推荐给黑客的五种语言在能力连续体上处于不同的位置。它们相对彼此的位置是一个敏感的话题。我想说的是,我认为Lisp位于顶端。为了支持这个说法,我将告诉你当我查看其他四种语言时发现缺失的东西。我想,怎么能在它们中完成任何事情,而没有宏呢?[5]

许多语言都有一种叫做宏的东西。但Lisp宏是独特的。信不信由你,它们的作用与括号有关。Lisp的设计者并不是为了与众不同而在语言中加入所有这些括号。对Blub程序员来说,Lisp代码看起来很奇怪。但这些括号是有原因的。它们是Lisp与其他语言之间根本差异的外在证据。

Lisp代码是由Lisp数据对象构成的。而不是在微不足道的意义上,源文件包含字符,字符串是语言支持的数据类型之一。Lisp代码在被解析器读取后,由你可以遍历的数据结构构成。

如果你理解编译器的工作原理,实际上发生的事情并不是Lisp有奇怪的语法,而是Lisp没有语法。你在其他语言被解析时生成的解析树中编写程序。但这些解析树对你的程序是完全可访问的。你可以编写操作它们的程序。在Lisp中,这些程序称为宏。它们是编写程序的程序。

编写程序的程序?你什么时候会想要这样做?如果你用Cobol思考,那并不常见。如果你用Lisp思考,那是随时都想做的。如果我能给出一个强大宏的例子,那就方便了,我会说,怎么样?但如果我这样做,它对不懂Lisp的人来说只会显得像胡言乱语;这里没有空间来解释你需要了解的所有内容,以理解它的含义。在 Ansi Common Lisp中,我尽量加快进度,尽管如此,我直到第160页才讲到宏。

但我认为我可以给出一种可能令人信服的论点。Viaweb编辑器的源代码中大约有20-25%是宏。宏比普通的Lisp函数更难编写,当不必要时使用它们被认为是坏风格。因此,代码中的每个宏都是因为必须存在而存在。这意味着该程序中至少有20-25%的代码在做一些你在其他语言中无法轻易做到的事情。无论Blub程序员对我对Lisp神秘力量的主张有多怀疑,这都应该让他感到好奇。我们并不是为了自己的娱乐而编写这些代码。我们是一家微小的初创公司,尽全力编程,以在我们与竞争对手之间设置技术障碍。

一个多疑的人可能会开始怀疑这里是否存在某种关联。我们代码中的一大部分在做一些在其他语言中非常难以做到的事情。最终的软件做了我们的竞争对手软件无法做到的事情。也许这里有某种联系。我鼓励你追踪这个线索。那个拄着拐杖的老人身上可能有更多的东西。

初创公司的合气道

但我不指望说服任何人 (超过25) 去学习 Lisp。本文的目的不是改变任何人的想法,而是安慰那些已经对使用Lisp感兴趣的人——那些知道Lisp是一种强大语言,但担心它不被广泛使用的人。在竞争环境中,这是一种优势。Lisp的力量因你的竞争对手不理解它而倍增。

如果你考虑在初创公司中使用Lisp,你不应该担心它不被广泛理解。你应该希望它保持这种状态。而且它很可能会保持这种状态。编程语言的特性使大多数人对他们当前使用的语言感到满意。计算机硬件的变化速度远远快于个人习惯,以至于编程实践通常落后于处理器十到二十年。在麻省理工学院等地方,他们在1960年代早期就开始用高级语言编写程序,但许多公司在1980年代仍继续用机器语言编写代码。我敢打赌,很多人直到处理器像一个急于关门回家的酒保,最终通过切换到RISC指令集将他们踢出。

通常,技术变化很快。但编程语言是不同的:编程语言不仅仅是技术,还是程序员的思维方式。它们一半是技术,一半是宗教。[6]因此,中位语言,即中位程序员使用的语言,移动得像冰山一样缓慢。垃圾回收,约在1960年由Lisp引入,现在被广泛认为是好事。运行时类型,亦然,正在逐渐流行。词法闭包,1970年代早期由Lisp引入,现在,勉强算是进入了雷达屏幕。宏,1960年代中期由Lisp引入,仍然是未知领域。

显然,中位语言具有巨大的惯性。我并不是提议你可以与这种强大的力量抗衡。我所提议的正好相反:就像合气道的练习者一样,你可以将其用作对抗对手的武器。

如果你在一家大公司工作,这可能并不容易。你很难说服那个尖头发的老板让你用Lisp构建东西,因为他刚在报纸上读到某种其他语言正准备像二十年前的Ada一样征服世界。但如果你在一家尚未有尖头发老板的初创公司工作,你可以像我们一样,利用布鲁布悖论为自己谋利:你可以使用你的竞争对手因固守中位语言而永远无法匹敌的技术。

如果你真的发现自己在一家初创公司工作,这里有一个评估竞争对手的实用技巧。阅读他们的招聘信息。网站上的其他所有内容可能都是库存照片或相应的文字,但招聘信息必须具体说明他们想要什么,否则他们会得到错误的候选人。

在我们为Viaweb工作期间,我阅读了很多职位描述。每个月似乎都有一个新竞争对手冒出来。检查他们是否有在线演示后,我做的第一件事就是查看他们的招聘信息。经过几年的这种观察,我可以判断哪些公司值得担心,哪些公司不值得担心。职位描述越有IT味道,公司的危险性就越小。最安全的类型是那些希望有Oracle经验的公司。你永远不必担心那些。如果他们说他们想要C++或Java开发人员,你也很安全。如果他们想要Perl或Python程序员,那就有点令人担忧——这开始听起来像是一家至少在技术方面由真正的黑客管理的公司。如果我曾经看到招聘Lisp黑客的职位发布,我会非常担心。

注释

[1] Viaweb最初有两个部分:用Lisp编写的编辑器,供人们用来构建他们的网站,以及用C编写的订单系统,处理订单。第一个版本主要是Lisp,因为订单系统很小。后来我们添加了两个模块,一个用C编写的图像生成器和一个主要用Perl编写的后台管理系统。

在2003年1月,雅虎发布了一个用C++和Perl编写的新版本编辑器。很难说这个程序是否不再用Lisp编写,因为为了将这个程序翻译成C++,他们实际上不得不编写一个Lisp解释器:据我所知,所有页面生成模板的源文件仍然是Lisp代码。(参见格林斯潘的第十条规则。)

[2] 罗伯特·莫里斯说我不需要保密,因为即使我们的竞争对手知道我们在使用Lisp,他们也不会理解为什么:“如果他们那么聪明,他们早就应该在用Lisp编程了。”

[3] 所有语言在图灵等价的意义上都是同样强大的,但这并不是程序员关心的意义。(没有人想用图灵机编程。)程序员关心的那种能力可能无法正式定义,但解释它的一种方法是说,它指的是你只能通过在较弱的语言中为更强大的语言编写解释器才能获得的特性。如果语言A有一个用于从字符串中删除空格的操作符,而语言B没有,这可能并不会使A更强大,因为你可能可以在B中编写一个子例程来做到这一点。但如果A支持递归,而B不支持,那就不太可能通过编写库函数来解决。

[4] 给极客的注:或者可能是一个格子,向上收窄;这里重要的不是形状,而是至少存在部分顺序的想法。

[5] 将宏视为一个独立特性有点误导。在实践中,它们的有用性因其他Lisp特性(如词法闭包和剩余参数)而大大增强。

[6] 结果,编程语言的比较要么表现为宗教战争,要么表现为如此坚定中立的本科教科书,以至于它们实际上是人类学的著作。重视和平或希望获得终身职位的人会避免这个话题。但这个问题只是一半的宗教问题;其中有值得研究的东西,尤其是如果你想设计新的语言。