### 12.拒绝平庸
1995年,罗伯特·莫里斯和我一起创办了Viaweb。我们打算开发软件,让用户可以自己搭建网上商店。当时,我们的创意是把软件放在服务器端,使用普通的网页作为用户界面。
当然,那个时候许多人可能都想到过这个主意。但是,就我所知,Viaweb是第一个互联网应用程序。在我们看来,这真的是很新颖的想法,所以我们就把公司命名为Viaweb,意即我们的软件通过网络使用,而不是运行在你的桌面电脑上^。
^「在英语中,via是一个介词,意为“经过……”,所以Viaweb的意思就是经过网络。——译者注」
另一个特别之处是,这个软件主要采用Lisp语言开发^。它是最早的用Lisp语言开发的大型应用程序,在此之前,Lisp语言主要用于大学和实验室中。
^「一开始的时候,Viaweb有两个部分——编辑器和订单处理系统。前者用Common Lisp开发,主要供用户搭建自己的网站。后者用C语言开发,主要用来处理订单。在Viaweb的第一版中,Lisp是最主要的开发语言,因为订单处理系统非常小,占用的代码很少。2003年1月,Yahoo发布了Viaweb编辑器的新版本,采用C++和Perl开发。但是,为了把原始程序翻译成C++,他们可能不得不专门写一个Lisp解释器,因为据我所知,Viaweb所有的页面生成模板还没变,都是使用Lisp代码。(参见Greenspun写的Tenth Rule一书第198页。)」
### 秘密武器
埃里克·雷蒙德写过一篇文章《如何成为一个黑客》(How to Become aHacker)。文中有一部分专门谈到,在他看来,如果你想当一个黑客,应该学习哪些语言。他建议从Python和Java入手,因为它们比较容易学。想当高级一点的黑客,还应该学习C和Perl。前者用来对付Unix系统,后者用来系统管理和开发CGI脚本。最后,真正非常严肃地把黑客作为人生目标的人,应该考虑学习Lisp:
> Lisp很值得学习。你掌握它以后,会感到它给你带来的极大启发。这会大大提高你的编程水平,使你成为一个更好的程序员。尽管在实际工作中极少会用到Lisp。
在讨论学习拉丁语有何价值时,你往往也会听到这一类的话。拉丁语无助于你找工作(也许古典文学教授的工作除外),但是它可以训练你的思维,帮助你更好地运用母语(比如英语)进行写作。
但是且慢,拉丁语的比喻并不完全适合Lisp语言。拉丁语无助于你找工作的原因是因为没有人说拉丁语。如果你用它写作,没有人能看懂。但是,Lisp是一种计算机语言,无论我们程序员使用哪一种语言与计算机交谈,它都能听懂。
如果埃里克·雷蒙德没有说错,Lisp语言确实可以使你成为更好的程序员,那么为什么你不使用它编程呢?如果画家有一支让他画得更好的画笔,我觉得他应该会用这支笔完成所有的画作,对不对?我在这里不是想证明埃里克·雷蒙德错了。他的观点整体上非常正确,他对Lisp语言的看法确实是大多数人的看法,但是这里面就是有一个矛盾:Lisp语言能让你成为更好的程序员,但你却不用它,这难道不奇怪吗?
为什么不用呢?编程语言毕竟是一种工具。如果Lisp语言真的能开发出更好的程序,你就应该用它。如果它无助于编程,那么就不会有人需要它。
这不仅仅是一个理论问题。软件业是竞争非常激烈的行业,而且容易出现垄断。在不考虑其他情况的条件下,某家公司的软件更快更好用,就会把竞争者赶出这个市场。一旦你开始创业,你就会更深切地感受到这一点。一般情况是,创业公司要么赢得一切,要么彻底失败。你要么成为富翁,要么一无所获。创业的时候,如果你选择了错误的技术,竞争对手就会一举打败你。
罗伯特·莫里斯和我都很了解Lisp语言,我们相信自己的直觉,找不出任何不使用它的理由。我们知道其他人都用C++或Perl开发软件, 但是我们不觉得这说明了什么问题。如果别人用什么技术,你也用什么技术,那么你大概只能使用Windows了。选择使用哪一种技术的时候,你不能考虑别人的做法,只能考虑什么样的技术能最好地完成工作。
![](https://box.kancloud.cn/2016-01-12_5694ae0a1340d.jpg)
图12-1 我和罗伯特·莫里斯在Viaweb,1996年年初
创业公司尤其如此。大公司可以互相模仿,但是创业公司就不行。我觉得很多人没有意识到这一点,尤其是一些创业者。
大公司每年平均成长大约10%。所以,如果你掌管一家大公司,只要每件事都做到大公司的平均水准,你就能得到大公司的平均结果,也就是每年成长大约10%。
如果你掌管创业公司,当然也可以这样。你把每件事都做到平均水准,就能得到平均结果。问题在于,小公司的平均结果就意味着关门倒闭。创业公司的生存率远低于50%。所以,如果你掌管创业公司,最好做一些独特的事情,否则就会有麻烦。
回到1995年,我们懂得一些竞争对手不懂的事情(至少在我们看来是如此),这些事情甚至直到今天都很少有人懂:如果开发只在自己服务器上运行的软件,这意味着你想用什么语言就能用什么语言。如果开发桌面软件,就完全不一样了,大多数情况下你只能使用操作系统所用的开发语言。10年前,开发桌面软件就意味着要使用C语言。但是,对于互联网软件,你能使用任何你想用的语言。如果你还同时拥有操作系统和语言的源码,那么你的自由就更大了。
但是,这种新出现的自由是一把双刃剑。既然你可以使用任何语言,你就不得不思考到底使用哪一种语言。如果你的公司对这种选择的自由视而不见,而竞争对手看到了,那么你就有被击败的危险。
如果选择哪种语言都行,你到底使用哪一种语言?我们选择Lisp。首先,很明显,对于这个市场来说,快速开发出产品是很重要的。我们所有人都是从零开始,所以能够快速做出新功能的公司就会取得巨大的竞争优势。我们知道Lisp语言真的非常合适快速开发软件,而且我们的软件运行在服务器端,你一写完代码就能发布出去,所以这又进一步放大了快速开发的效果。
如果其他公司不想使用Lisp语言,那就更好了。这会让我们拥有技术优势。我们不能放过任何有利的因素。创办Viaweb的时候,我们对于如何经营一家公司毫无经验,对市场推广、雇用员工、融资、发展新客户等都一无所知。在此之前,我和莫里斯甚至连一夭正式上班的经历都没有。我们唯一擅长的事情就是开发软件。我们希望这一点可以弥补我们的劣势。任何在软件开发上面有助于我们获得优势的事情我们都不能放过。
可以这样说,我们使用Lisp只是一个大胆的冒险。我们设想如果用Lisp语言开发自己的软件,就能比竞争对手更快地写出新功能,还能做到他们做不到的事情。同时,因为Lisp是一种抽象层次非常高的语言,所以就不需要非常庞大的开发团队,这会降低成本。如果我们的设想是正确的,那么我们就能用更少的钱做出一个更好的产品,从而获得利润。最终,我们将独占市场,竞争对手什么也得不到,到头来只能退出这个行业。我们当时心里就是这么盘算的。
这次冒险的结果如何?多少有点出人意料,它竟然达到了我们的设想。我们前前后后遭遇到很多竞争对手,一共大概有二三十个,但是他们的软件没有一个能与我们竞争。我们的软件运行在服务器端,用户可以“所见即所得”地搭建网上商店,感觉就像在操作桌面软件。我们的竞争对手使用CGI脚本。我们在功能上总是遥遥领先于他们。有时,他们出于绝望,试图引入我们没有的功能。但是,有了Lisp语言的帮助,我们的开发周期很短。有时候,竞争对手刚刚发布新闻稿宣布将引入新功能,我们就能在一两天内做出自己的版本。当对手找来的记者抽出时间打电话过来想了解我们的反应,我们就会告诉他我们已经有了这个功能。
竞争对手一定觉得我们好像拥有了某种秘密武器,能够破解他们内部的通信或者其他机密。事实上,我们的确拥有秘密武器,但是没他们想的那么复杂。从来没有人向我们泄露他们的内部机密,只是我们的开发速度比别人想象的更快而已。
9岁时,我碰巧读过弗雷德里克·福赛思的小说《刺杀戴高乐》(The Day of the Jackal)。小说的主角是一个刺客,有人雇他暗杀法国总统。那个刺客必须通过警察的岗哨才能到达可以俯视总统行进路线的公寓。他扮成柱着拐杖的老头从警察身边经过,没有引起任何人的怀疑。
我们的秘密武器很类似上面的情景。我们使用一种奇特的人工智能语言开发软件,它的语法非常古怪,大量使用括号。多年来,要是听到别人这样描述Lisp语言,我会勃然大怒。但是现在,这却成了我们的优势。在竞争中,你的对手无法理解你的技术优势,这可是再宝贵不过了。商场如战场,对手摸不透你,你的胜算就增加了。
虽然有些令人难为情,但是我必须承认,就是因为这个原因,在Viaweb创业期间我从来没有公开谈论过Lisp语言。我们对新闻媒体闭口不谈Lisp,如果你在我们的网站上捜索Lisp,只会发现我在个人介绍中提到过两次,那是我写的两本关于Lisp的书。这是故意的,创业公司对竞争对手应该越保密越好。如果他们不知道(或者不关心)我们的软件用什么语言开发,我就要把这个秘密保持下去^。
^「莫里斯觉得不用这么保密,因为即使竞争对手知道我们使用Lisp语言,对他们也不会有帮助:“如果他们真的聪明,早就已经在用Lisp编程了。”」
最了解我们技术的人就是客户。他们不关心Viaweb用什么语言开发,但是发现它真的很好用。Viaweb可以让用户在几分钟内搭建起漂亮的网上商店。因此,主要通过口碑效应,我们得到了越来越多的新客户。1996年年底,我们支持的网上商店大约是70家。1997年,变成了500家。6个月后,雅虎收购我们的时候,我们有1070个用户。更名为Yahoo Store之后,这个软件继续主导市场,它是雅虎获利最丰厚的业务之一,用它搭建的商店成为“雅虎购物”(Yahoo Shopping)的基础。我在1999年离开了雅虎,所以不知道现在的准确用户数量,但是我上一次听到的数字是超过了2万。
### Blub困境
Lisp语言到底好在什么地方?如果它真的这么好,为什么没有得到广泛使用呢?这种问题听起来有点像绕口令,但是实际上回答起来很简单。Lisp语言的好处不在于它有一些狂热爱好者才明白的优点,而只在于它是目前最强大的编程语言。它没有得到广泛使用的原因就是因为编程语言不仅仅是技术,也是一种习惯性思维,非常难于改变。当然,上面两句话都需要进一步解释。
我先从一个争议极大的命题开始讲起:编程语言的编程能力有差异。至少不会有人反对高级语言比机器语言更强大这一观点。今天的大多数程序员通常情况下都不会想用机器语言编程,而是使用一种高级语言,然后再让编译器帮你把它翻译成机器语言。这种观念甚至已经移植到了硬件,从20世纪80年代开始,硬件的指令集都是针对编译器而不是针对程序员设计的。
大家都知道,徒手用机器语言写出整个程序是一件很蠢的事。但是,把这个观点推广到一种更普遍的情况,知道的人就不多了。如果你有好几种语言可以选择,在不考虑其他因素的情况下,你不选择最强大的那种语言就是一件很蠢的事^。
^「如果从图灵等价(Turing-equivatent)的角度来看,所有语言都是一样强大的,但是这对程序员没有意义。(没人想为图灵机编程。)程序员关心的那种强大也许很难正式定义,但是有一个办法可以解释,那就是有一些功能在一种语言中是内置的,但是在另一种语言中需要修改解释器才能做到,那么前者就比后者更强大。如果A语言有一个运算符,可以移除字符串中的空格,而B语言没有这个运算符,这可能不足以称A语言比B语言强大,因为你可以在B语言里写一个函数实现这个功能。但是,如果A语言支持某种高级功能(假定是递归),而B语言不支持,你就不可能通过自己编写函数库解决了,所以这就代表A语言比B语言更强大。」
上面这个观点有许多例外情况。如果在开发的程序必须与另一个程序紧密配合,那么可能最好还是使用后者的开发语言。如果你的程序只是要做一些很简单的事(比如整数运算或者位操作),那就不妨使用一种比较靠近机器的低层次语言,主要原因是这样运行起来会更快一些。如果你的程序很短,只是为了特定场合一次性使用,那么你最好根据自己要解决的问题选择具有最强大函数库的语言,不过,总的来看,对于应用程序来说,还是应该选择总体最强大、效率也在可接受范围内的编程语言,否则都是不正确的选择,就好像你选择机器语言编程一样,只是程度上有差异而已。
大家都公认机器语言属于非常低层次的语言。但是,至少在社会上很多人眼里,高级语言其实也差不多。但事实并非如此,高级语言与机器语言的差别很大。从技术上看,“高级语言”并不是一个定义很清晰的名词。在高级语言与机器语言之间并不存在一条明确的分界线。语言的抽象性是一条连续曲线,从最强大的语言一直到最底层的机器语言,每一种语言的能力都有差异^。
^「语言之间的关系或许还可以比喻成栅格结构(lattice),从下往上朝着顶端慢慢收窄。具体的形状在这里并不重要,重点是语言之间至少存在着一种偏序关系(partial order)。」
以Cobol语言为例,通过编译器,它可以被编译成机器语言。从这个角度来说它是一种高级语言。但是,有谁会真的把Cobol当成与其他高级语言(比如Python)—样强大的语言?比起Python,它可能更接近机器语言。
Perl 4如何?与Perl 5相比,它不支持闭包。所以,大多数Perl的黑客都认为Perl 5比Perl 4更强大。如果你同意这一点,就意味着你也认可一种高级语言可以比另一种高级语言更强大。因此,必然能够接着推导出,除了某些特殊情况,你就是应该使用目前最强大的语言。
不过在现实中这个结论很少能落实。到了一定年龄之后,程序员极少主动更换自己的编程语言。不管习惯使用的是哪一种语言,他们往往认为这种语言已经足够好了。
程序员非常忠于他们心爱的语言,我不想伤害任何人的感情,所以为了解释我的观点,我假设有一种Blub语言。它的抽象程度正好落在编程能力曲线的中点。它不是最强大的语言,但是要比Cobol或机器语言更高级。
我们假设Blub程序员既不使用机器语言也不使用Cobol语言。他认为前者是编译器的工作,后者他不知道有什么用(Cobol语言甚至连XX功能也没有,Blub语言就具备这个功能)。
只要这位程序员向曲线下方望去,他就肯定知道自己正在看的是一些比较低层次的语言。因为那些语言明显不如Blub语言强大,缺少他习惯使用的某些功能。但是,当他向曲线上方望去,他不会意识到自己正在看更高层次的语言,而是仅仅觉得自己正在看某些奇怪的语言。他可能认为那些语言也许与Blub一样强大,但是加入了不少怪东西。他觉得Blub语言已经够用了,不用再考虑那些语言了。这时,他的思维就是已经被Blub同化了。
但是,当我们转换视角,把自己想象成使用曲线更上方某一种语言的程序员并往下看的时候,我们就会发现,自己也同样轻视Blub语言。你怎么用Blub语言完成工作呢?它甚至连YY功能都没有!
通过归纳法我们就会知道,唯一洞悉所有语言优劣的人必然是懂得最强大的那种语言的人。(这大概就是埃里克·雷蒙德所说的Lisp语言使你成为一个更好的程序员的意思。)由于Blub困境的存在,你无法信任其他人的意见:他们都满足于自己碰巧用熟了的那种语言,他们的编程思想都被那种语言主宰了。
我自己的经历也证实了这个看法。高中时我喜欢用Basic语言编程。这种语言功能很弱,甚至不支持递归,很难想象没有递归还怎么编程。但是我那时根本没觉得有损失,Basic语言控制了我的思维。当时我非常精通Basic语言,只要是学过的部分都能熟练地使用。
雷蒙德推荐的五种黑客应该学会的语言,其强大程度各有不同,分布在编程能力曲线五个不同的点上。它们的相对位置是一个敏感的话题。我只想说,我认为,Lisp语言在最上方。为了证明这个论断,让我告诉你,我发现Lisp有一个功能,其他四种语言都没有。我觉得,没有宏(macro)的话,那些语言怎么编程呢^?
^「把宏说成一种独立的功能有误导之嫌。在实际运用中,如果没有其他Lisp功能(比如闭包和函数的rest参数)的配合,Lisp的宏也不会有太大作用。」
许多语言自称也有宏,但是Lisp的宏是独一无二的。信不信由你,Lisp宏的作用与括号有关。Lisp语言的设计者大量使用括号并不是为了标新立异。Blub语言的程序员会觉得Lisp代码看上去很怪,有那么多括号,但这是有原因的。它们是Lisp与其他语言存在巨大差异的外在表现。
Lisp代码由Lisp数据对象构成。其他语言的源代码一般由字符组成,字符串是主要数据类型之一,但是Lisp语言不完全是这样。经过解析器处理之后,Lisp代码就变成了你可以遍历的数据结构。
如果你理解编译器的工作原理,那么事实是,与其说Lisp有一种很奇特的语法,还不如说它根本没有语法。一般的源代码程序经过编译器解析会生成解析树。Lisp的奇特之处就在于,你可以完全写出程序,控制这种解析树,进行任意的存取操作。Lisp的这种程序就叫做宏,它们可以用来生成其他程序。
生成其他程序的程序?什么时候需要用到它们?如果你用Cobol语言思考,会觉得很少需要用到它们。如果你用Lisp语言思考,会发现它们无所不在。我要是在这里举一个Lisp宏功能强大的实例,可能更便于说明问题。你看这个例子!是不是很方便啊?但是如果这样做,对于不懂Lisp语言的人来说,这篇文章就不知所云了。本文没有办法把所有事情都解释清楚,无法帮助你彻底理解这门语言。我在Ansi Common Lisp一书中已经尽可能地简化内容、快速讲解,但是也要到全书篇幅将近一半的地方(第11章)才能讲到宏。
但是我想可以给出事实证明我的这个观点。Viaweb编辑器的源码之中大约20%~25%是宏。它们比普通的Lisp函数难写,而且如果用在不必要的地方,反而是一种很不良的编程习惯。所以,我们代码中的每一个宏都有充分的使用理由。这意味着这个程序至少20%~25%代码的功能无法轻易地用其他语言实现。我在前文一再声称Lisp语言无比强大,无论Blub语言的程序员对此多么怀疑,看到这个事实应该足以让他感到很好奇,我们居然用到了这么多宏。我们这样写代码并不是为了好玩。我们是一家小创业公司,拚尽全力写代码,只是为了给竞争对手布下重重障碍,不让他们赶上来。
抱有怀疑态度的人可能会想上面的论断是否成立,两者之间是否存在相关关系。我们的一大块代码能够做到其他语言很难做到的事。只凭这一点是否能得出结论:我们的软件能够做到竞争对手的软件做不到的事?我必须说,这里面可能就是存在相关关系。我鼓励你继续深入思考这个问题。表面上,一个老年人拄着拐杖蹒跚而行,你不要只是看看而已,他背后可能有更多的故事值得了解,你应该想得更深一些。
### 创业公司的合气道^
^「合气道(Aikido)是一种日本的武术,主要特点是“以柔克刚”、“借劲使力”、“不主动攻击”。——译者注」
尽管Lisp语言非常强大,但是我并不期望有谁(超过25岁的人)读完这篇文章就立刻开始学习它。我写这篇文章的目的不是想改变任何人的观点,而是想让那些有兴趣学习Lisp语言的人放心,他们知道Lisp是一种强大的语言,但是担心使用者太少,学会了也没什么用。我想让他们明白,在商业竞争中使用Lisp语言就会带来优势。你的竞争对手不懂Lisp,这将使得它的强大更充分地表现出来。
如果你想在创业公司中使用Lisp语言,你不仅不应该担心使用它的人太少,反而应该希望这种局面保持下去。事实上,现状很可能真的会保持下去。因为编程语言的特点之一就是它会使得大多数使用它的人满足于现状,不想改用其他语言。人类天性变化的速度大大慢于计算机硬件变化的速度,所以编程语言的发展通常比CPU的发展落后一二十年。在麻省理工学院这样的地方,20世纪60年代初就开始使用高级语言了。但是,许多公司直到80年代还在用机器语言编程。我敢打赌,很多人对机器语言恋恋不舍,直到CPU开始采用精简指令集^了才不得不放弃使用机器语言。这就好比酒吧已经到了打烊时间,酒保开始整理桌子、收拾东西准备回家,客人才被迫离开。
^「精简指令集计算机(Reduced Instruction Set Computer,简称RISC)是CPU的一种架构,对指令数目和寻址方式都做了精简,使其实现更容易,执行速度更快,编译器的效率更高。它在20世纪80年代开始得到大规模采用。——译者注」
技术的变化速度通常是很快的。但是,编程语言不一样,与其说它是技术,还不如说是程序员的思考模式。编程语言是技术和宗教的混合物^。所以,一种很普通的编程语言就是很普通的程序员使用的语言,它的变化就像冰山那样缓慢。大概在1960年,Lisp语言引入了垃圾回收机制(Garbage Collection),今天已经被广泛认为是非常好的做法。Lisp的动态类型特点也同样受到越来越多人的认同。闭包是20世纪60年代Lisp语言引入的功能,现在的接受程度还很低。宏也是60年代中期Lisp语言引入的,现在还是一片处女地。
^「所以,如果你想对编程语言进行比较,那就做好准备打一场宗教战争,或者索性就写一本绝对不带个人色彩的大学教材,枯燥得像人类学研究一样。那些喜欢平静生活的人以及想要得到终身教职的人对这个话题唯恐避之不及。但是,必须承认的是,它只是一半与宗教有关,所以剩下的一半依然值得研究,尤其是当你要设计新语言的时候。」
很显然,那些很普通的编程语言正在主导一切。我不建议你挑战这种强大的习惯势力,相反,我建议你向日本合气道选手学习,利用这种势力削弱你的竞争对手,让他们自食其果。
如果你为大公司工作,想要改用Lisp语言可能不是一件容易的事。你很难说服自以为是的老板,让他允许你用Lisp语言开发程序。老板受到报纸的影响,认为某些其他语言将主宰世界(就像20年前Ada语言受到的评价)。但是,如果你为创业公司工作,那里没有这样的老板,那么你就能和我们一样,将他人的Blub困境转变为你的优势。你的竞争对手被牢牢粘在那些很普通的语言上面,永远都追不上你使用的技术。
如果你为创业公司工作,那么这里有一个评估竞争对手的妙招——关注他们的招聘职位。他们网站上的其他内容无非是一些陈腐的照片和夸夸其谈的文字,但是招聘职位却不得不写得很明确,反映出他们到底想干什么,否则就会引来一大批不合适的求职者。
在Viaweb创业期间,我读过大量竞争对手的招聘职位。差不多每个月都有一个新的竞争对手浮出水面。我首先会看他们的产品有没有一个试用版,然后就去找他们的招聘职位。这样过了几年,我就知道哪些公司值得关注,啷些公司不用在意。有些公司的职位描述使用了大量的IT词汇,这样的内容越多,这家公司就越不构成威胁。最不用担心的竞争对手就是那些要求应聘者具有Oracle数据库经验的公司,你永远不必担心他们。如果是招聘C++或Java程序员的公司,对你也不会构成威胁。如果他们招聘Perl或Python程序员,就稍微有点威胁了。至少这听起来像一家技术公司,并且由黑客控制。如果我有幸见到一家招聘Lisp黑客的公司,就会真的感到如临大敌。