打败平均水平
OriginalApril 2001, rev. April 2003
(本文改编自 2001 年 Franz 开发者研讨会上的演讲。)
1995 年夏天,我和我的朋友罗伯特·莫里斯创办了一家名为 Viaweb 的创业公司。 我们的计划是编写 软件,让最终用户能够建立在线商店。 当时,这款软件的新颖之处在于 它运行在我们的服务器上,使用普通的网页 作为界面。
当然,很多人可能在同一时间有这个想法,但据我所知,Viaweb 是第一个基于 Web 的应用程序。 它对我们来说是一个如此 新颖的想法,以至于我们以它命名了公司: Viaweb,因为我们的软件通过 Web 工作, 而不是运行在您的台式电脑上。
这款软件的另一个不寻常之处在于它 主要用一种叫做 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 的级别很高,我们不需要 一个庞大的开发团队,所以我们的成本 会更低。 如果是这样,我们可以以更低的价格提供更好的产品 ,并且仍然可以盈利。 最终我们将获得 所有用户,而我们的竞争对手将一个也拿不到,最终 会破产。 这就是我们希望发生的事情。
这个实验的结果如何? 有点令人惊讶的是, 它成功了。 我们最终有了很多竞争对手,大约 有 20 到 30 个,但他们的软件都无法与 我们的软件竞争。 我们有一个运行在服务器上的所见即所得的在线商店构建器,但感觉 像一个桌面应用程序。 我们的竞争对手 有 cgi 脚本。 而且我们在功能方面总是领先于他们。 有时,在绝望的情况下,竞争对手会尝试引入 我们没有的功能。 但有了 Lisp,我们的开发周期 非常快,以至于我们有时可以在竞争对手在新闻稿中宣布新功能后的 一两天内复制它。 当报道新闻稿的记者开始联系 我们时,我们也会有这个新功能。
对我们的竞争对手来说,我们似乎拥有某种 秘密武器——我们正在破译他们的 Enigma 通信,或者 类似的东西。 事实上,我们确实拥有秘密武器,但它比 他们意识到的要简单。 没有人将他们的功能泄露给我们。 我们只是能够比任何人都快地开发软件。
当我大约 9 岁的时候,我偶然得到了一本弗雷德里克·福赛斯的《豺狼的日子》的副本。 主角是一名 刺客,受雇刺杀法国总统。 刺客 必须避开警察,才能到达一间俯瞰总统路线的公寓。 他装扮成 一个拄着拐杖的老人,从他们身边走过,他们从未怀疑过他。
我们的秘密武器类似。 我们用一种奇怪的 AI 语言编写了我们的软件,这种语言的语法很奇怪,充满了括号。 多年来,听到人们这样描述 Lisp 一直让我很恼火。 但现在它 对我们有利。 在商业中,没有什么比 竞争对手不理解的技术优势更宝贵了。 在 商业中,就像在战争中一样,出其不意与力量一样重要。
因此,我有点不好意思地说,在我们开发 Viaweb 的过程中,我从未公开谈论过 Lisp。 我们从未 向媒体提及过它,如果你在我们网站上搜索 Lisp,你只会找到我个人简介中两本书的标题。 这不是偶然的。 创业公司应该尽可能少地向竞争对手提供信息。 如果他们不知道我们的软件是用什么语言编写的,或者不在乎,我想保持这种状态。[2]
最了解我们技术的人是客户。 他们也不在乎 Viaweb 是用什么语言编写的,但 他们注意到它运行得非常好。 它让他们能够在几分钟内建立外观精美的 在线商店。 因此,主要通过口口相传,我们获得了越来越多的用户。 到 1996 年底,我们 大约有 70 家在线商店。 到 1997 年底,我们有 500 家。 六 个月后,雅虎收购了我们,我们拥有 1070 个用户。 今天,作为 雅虎商店,这款软件继续主导着它的市场。 它是 雅虎最赚钱的产品之一,用它构建的商店是雅虎购物的基础。 我于 1999 年离开了雅虎,所以我不确定他们现在有多少用户,但我 最后一次听说大约有 20,000 个。
Blub 悖论
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 使你成为更好的程序员的意思。)你不能 相信其他人的意见,因为 Blub 悖论: 他们对他们碰巧使用的任何语言都感到满意,因为 它决定了他们思考程序的方式。
我从自己的经验中了解到这一点,作为一个在高中用 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,你不应该担心 它没有被广泛理解。 你应该希望它保持这种状态。 而且很可能会这样。 编程语言的本质就是让大多数人对他们目前使用的语言感到满意。 计算机硬件的变化速度比个人习惯快得多,以至于 编程实践通常比处理器落后 10 到 20 年。 在麻省理工学院这样的地方,人们在 1960 年代初就开始用 高级语言编写程序,但许多公司一直到 1980 年代还在用机器语言编写代码。 我敢打赌,很多人一直到处理器,就像一个渴望关门回家睡觉的酒保一样,最终通过切换到 risc 指令集将他们赶走才停止使用机器语言。
通常情况下,技术变化很快。 但编程语言不同:编程语言不仅仅是技术,而是 程序员思考的方式。 它们一半是技术,一半是宗教。[6] 因此,中间语言,也就是大多数程序员使用的语言,移动得像冰山一样慢。 垃圾回收,由 Lisp 在大约 1960 年引入,现在被广泛认为是 一件好事。 运行时类型,同样,越来越受欢迎。 词法闭包,由 Lisp 在 1970 年代初引入,现在,仅仅 出现在雷达屏幕上。 宏,由 Lisp 在 1960 年代中期引入,仍然是未知领域。
显然,中间语言拥有巨大的动量。 我并不是 建议你可以与这股强大的力量抗衡。 我建议的恰恰相反:就像合气道练习者一样,你可以 利用它来对付你的对手。
如果你在一家大公司工作,这可能不容易。 你将很难说服那些头发尖尖的老板让你用 Lisp 构建东西,因为他刚刚在报纸上读到,像 Ada 二十年前一样,某种语言即将 接管世界。 但如果你在一家还没有 头发尖尖的老板的创业公司工作,你可以,就像我们一样,将 Blub 悖论变成你的优势:你可以使用你的 竞争对手永远无法匹敌的技术,他们被牢牢地粘在中间语言上。
如果你真的发现自己在一个创业公司工作,这里有一个方便的 评估竞争对手的技巧。 阅读他们的招聘信息。 他们网站上的其他所有内容可能都是库存照片或文字等价物, 但招聘信息必须明确说明他们想要什么,否则 他们会招到错误的人。
在我们开发 Viaweb 的几年里,我阅读了很多招聘信息。 每个月都会出现一个新的竞争对手,仿佛从地下冒出来一样。 我做的第一件事,是在查看他们是否有 一个在线演示之后,就是查看他们的招聘信息。 经过几年的观察,我就能判断出哪些公司值得担心,哪些不值得担心。 招聘信息越偏向 IT,这家公司就越不危险。 最安全的类型是那些需要 Oracle 经验的公司。 你永远不必担心那些公司。 如果你需要 C++ 或 Java 开发人员,你也是安全的。 如果他们需要 Perl 或 Python 程序员,那就有点可怕了——这听起来像是一家 技术方面,至少,是由真正的黑客管理的公司。 如果我 曾经看到过一个招聘 Lisp 黑客的职位,我会非常担心。
注释
[1] Viaweb 最初有两个部分:编辑器,用 Lisp 编写, 人们用它来构建他们的网站,以及订购系统, 用 C 编写,用于处理订单。 第一个版本主要是 Lisp,因为订购系统很小。 后来我们又添加了两个 模块,一个用 C 编写的图像生成器,以及一个主要用 Perl 编写的后台管理系统。
2003 年 1 月,雅虎发布了用 C++ 和 Perl 编写的编辑器的新版本。 不过,很难说这个程序是否不再用 Lisp 编写,因为为了将这个程序 翻译成 C++,他们实际上不得不编写一个 Lisp 解释器:所有页面生成模板的源文件仍然是,据我所知,Lisp 代码。(参见 Greenspun's Tenth Rule。)
[2] 罗伯特·莫里斯说,我不需要保密,因为 即使我们的竞争对手知道我们正在使用 Lisp,他们也不会 理解原因:“如果他们那么聪明,他们早就 用 Lisp 编程了。”
[3] 所有语言在图灵等价的意义上都同样强大,但这并不是程序员关心的意义。(没有人想编程一个图灵机。) 程序员关心的那种 力量可能无法正式定义,但 一种解释方法是说它指的是你只能在能力较弱的语言中通过编写 更强大语言的解释器来获得的功能。 如果语言 A 有一个用于从字符串中删除空格的操作符,而语言 B 没有,这可能不会使 A 更强大,因为你 可能可以在 B 中编写一个子程序来完成它。 但如果 A 支持, 比如,递归,而 B 不支持,那么这不太可能 是你可以通过编写库函数来解决的问题。
[4] 提醒一下极客:或者可能是格栅,向顶部收缩; 这里重要的不是形状,而是存在至少一个偏序关系的想法。
[5] 将宏视为一个单独的功能有点误导。 实际上,它们的用处在很大程度上受到其他 Lisp 功能(如词法闭包和剩余参数)的增强。
[6] 因此,对编程语言的比较要么采取宗教战争的形式,要么采取大学教科书的形式,这些教科书坚决 保持中立,以至于它们实际上是人类学著作。 珍惜和平的人,或者想要获得终身教职的人,都会避开这个话题。 但这个问题只有一半是宗教问题;这里确实有一些值得 研究的东西,尤其是如果你想设计新的语言。