譯者:Sander 發(fā)布:2007-08-24 16:16:05
百年語(yǔ)言 Paul Graham2003年4月 (本文出自2003年Python大會(huì)上的一篇主題講話) 很難預(yù)測(cè)人 們的生活在一百年后會(huì)是什么樣子,我們只能給很少的事物一個(gè)確切的預(yù)測(cè)。我們知道到那時(shí)候每個(gè)人都將駕駛氣墊轎車,地方法規(guī)將對(duì)建造上百層的高樓無(wú)所制約,大部分時(shí)間都將日月無(wú)光,女人們都將精通武術(shù)(martial arts)……在這里,讓我們把這幅圖景的一個(gè)細(xì)節(jié)放大來(lái)看看:那時(shí)候人們用什么編程語(yǔ)言來(lái)寫那些氣墊轎車的控制軟件呢?
這是一個(gè)值得思考的問題,其意義不在于我們一定要用這種語(yǔ)言,而是在于據(jù)此我們可以選擇可能發(fā)展成那種語(yǔ)言的語(yǔ)言——如果我們夠幸運(yùn)的話。
我認(rèn)為,語(yǔ)言就像物種一樣,會(huì)形成進(jìn)化樹,沒有前途的分支將枯死脫落。我們已經(jīng)看到了這種事情發(fā)生:Cobol——曾幾何時(shí)風(fēng)光無(wú)限,現(xiàn)如今沒有一個(gè)像樣的后代,它就是在進(jìn)化中被淘汰的“穴居人”語(yǔ)言。(譯注:穴居人是石器時(shí)代的歐洲大陸的主宰,大約3萬(wàn)年前滅絕。穴居人又叫尼安德特人,其發(fā)聲系統(tǒng)不發(fā)達(dá)。) 我預(yù)測(cè)Java的氣數(shù)也跟這種語(yǔ)言差不多。有人不時(shí)發(fā)郵件跟我說(shuō):“你怎么能說(shuō)Java不可能成為一種成功的語(yǔ)言呢?它現(xiàn)在已經(jīng)是一種相當(dāng)成功的語(yǔ)言了?!蹦敲次页姓J(rèn)這一點(diǎn)——如果你衡量成功的標(biāo)準(zhǔn)是關(guān)于Java的書籍(特別是個(gè)人著作)在書架上占去的空間的大小,或者是為了找工作不得不學(xué)習(xí)Java的大學(xué)生的數(shù)量的多少的話。我所說(shuō)Java不可能成為一種成功的語(yǔ)言,意思是從物種進(jìn)化的角度來(lái)看,Java將會(huì)走向窮途末路,就像Cobol一樣。 這只是一個(gè)猜想,我也許會(huì)猜錯(cuò)。我在此的重點(diǎn)不是要討論Java,而是要提出進(jìn)化樹的論點(diǎn)并引發(fā)人們來(lái)問自己:“X語(yǔ)言在進(jìn)化樹上的什么位置?”之所以提出這個(gè)問題,不僅為了避免百年后去后悔,更主要是因?yàn)楦o語(yǔ)言發(fā)展的主流對(duì)于當(dāng)前選擇好的編程語(yǔ)言有積極的啟發(fā)意義。 假如你生活在舊石器時(shí)代,任何時(shí)候你大概都會(huì)因?yàn)樽约骸疤幵谶M(jìn)化樹的主干上”(譯注:石器時(shí)代地球上生活著智人在內(nèi)的多個(gè)人種,后來(lái)其他人種都滅絕了,只有智人在競(jìng)爭(zhēng)中生存下來(lái),成為現(xiàn)代人類的祖先)而感到無(wú)比幸福,雖然還有大量的穴居人——他們也是這個(gè)世界的居民,并且克魯馬努人(譯注:舊石器時(shí)代晚期在歐洲的高加索人種)不時(shí)會(huì)來(lái)襲擊你,還偷走你的食物。 因此我也想知道編程語(yǔ)言在一百年以后會(huì)是什么樣子,從而決定現(xiàn)在該把賭注押在哪個(gè)“樹枝”上。
編程語(yǔ)言的進(jìn)化過程又不同于物種的進(jìn)化過程,因?yàn)榫幊陶Z(yǔ)言的分支可能會(huì)匯聚。譬如Fortran這個(gè)分支,似乎正在漸漸并入到Algol的后代中。理論上講這對(duì)于物種來(lái)說(shuō)也是可能的,但是這種可能性很小,似乎從來(lái)就沒有發(fā)生過。 集中化對(duì)于語(yǔ)言的進(jìn)化更有可能,部分原因是語(yǔ)言進(jìn)化的走向空間比較小,還有部分原因是對(duì)語(yǔ)言的進(jìn)化來(lái)說(shuō),突變不是隨機(jī)的。語(yǔ)言的設(shè)計(jì)者總會(huì)有意識(shí)地吸取其他語(yǔ)言的思想。 對(duì)于語(yǔ)言設(shè)計(jì)者來(lái)說(shuō),考慮一下編程語(yǔ)言的進(jìn)化方向就特別有意義,因?yàn)樗麄兛梢該?jù)此把握好設(shè)計(jì)取向。在那種情況下,“處在進(jìn)化樹的主干上”就不只是選擇一個(gè)好的語(yǔ)言了,而是從中得到啟發(fā),以對(duì)語(yǔ)言的設(shè)計(jì)做出正確的決策。
任何編程語(yǔ)言都可以分為兩個(gè)部分:作為公理(axiom)的一個(gè)基本運(yùn)算符(operator)集和語(yǔ)言的其他部分,其他部分原則上可以根據(jù)基本語(yǔ)素寫出來(lái)。我想基本語(yǔ)素集是一種語(yǔ)言在其漫長(zhǎng)的生存期中最重要的部分了,而其他部分可能會(huì)改變。這就好比買一幢房子,原則上你應(yīng)該首先考慮房子的地理位置,其他的任何因素你都可以調(diào)整,但是你不能調(diào)整位置。 我認(rèn)為好的公理的選擇很重要,但是公理要盡量少,這一點(diǎn)同樣重要。數(shù)學(xué)家們對(duì)于這一點(diǎn)感受應(yīng)該更深刻:公理越少越好。我認(rèn)為也確實(shí)如此。 最近,人們仔細(xì)核查起編程語(yǔ)言的核心,看看是不是有什么“公理”是可以除去的,這已經(jīng)成為一項(xiàng)有益的實(shí)踐。我發(fā)現(xiàn)在我長(zhǎng)期的職業(yè)生涯里,自己經(jīng)常像個(gè)笨蛋一樣,用垃圾堆積著垃圾(譯注:原文cruft breeds cruft,隨著軟件的發(fā)展,以及經(jīng)歷了修改bug和更新的若干周期,它的部分代碼已不再使用但仍然保留在源碼中。這種代碼稱為cruft。 cruf可能是一兩行無(wú)用代碼或整個(gè)源文件模塊。由于很難識(shí)別cruft,去除cruft 往往很困難。)并且我發(fā)現(xiàn)同樣的事情在軟件里隨時(shí)隨地都在發(fā)生。 我有一個(gè)預(yù)感,軟件進(jìn)化樹的主干會(huì)貫穿于某些編程語(yǔ)言中,這些語(yǔ)言有著最小、最干凈的“核”。一種語(yǔ)言越能用它自己來(lái)寫自己,就越好。
當(dāng)然,在提出一百年后編程語(yǔ)言會(huì)是什么樣子的問題的時(shí)候,我做了一個(gè)很大的假設(shè)。一百年后我們還寫程序嗎?我們不是只需要告訴計(jì)算機(jī)我們希望他們做什么就可以了嗎?到現(xiàn)在為止,這方面還沒有大的進(jìn)展。我想此后的一百年里,人們還是要通過現(xiàn)在這樣手工編寫的程序來(lái)告訴計(jì)算機(jī)去做什么?;蛟S有的問題我們現(xiàn)在需要寫程序來(lái)解決,而一百年后這些問題不必再寫程序來(lái)解決,但是我想我們還是要面對(duì)很多我們今天編程所面臨的同樣的問題。 誰(shuí)要說(shuō)他能預(yù)測(cè)某一技術(shù)在一百年后將是什么樣子,我們都會(huì)覺得他在吹牛。但是不要忘記我們已經(jīng)有了五十年的經(jīng)驗(yàn),當(dāng)我們反思過去的五十年里語(yǔ)言的進(jìn)化是多么緩慢的時(shí)候,再來(lái)展望一下一百年后的情況就是一件可以理解的事。 語(yǔ)言進(jìn)化緩慢,是因?yàn)樗鼈儾⒉皇羌夹g(shù),語(yǔ)言只是符號(hào)。程序只是告訴計(jì)算機(jī)你要解決的問題的形式化的描述。編程語(yǔ)言的進(jìn)化的速度并不像搬運(yùn)或傳遞,倒更像數(shù)學(xué)符號(hào)的進(jìn)化速度——數(shù)學(xué)符號(hào)也在進(jìn)化,但是如你所見,卻不像它所支持的技術(shù)一樣有巨大而飛快的變化。
無(wú)論一百年后計(jì)算機(jī)是什么材料做的,可以很肯定地預(yù)測(cè)它將比現(xiàn)在運(yùn)行更快。如果摩爾定律(Moor’s Law)繼續(xù)有效的話,它的速度將是現(xiàn)在的7,379億億(quintillion)(73,786,976,294,838,206,464)倍,這是難以想象的。不可否認(rèn),對(duì)于速度的預(yù)測(cè)摩爾定律很可能失效,任何事物如果每18個(gè)月就增長(zhǎng)一倍的話,長(zhǎng)到最后就很可能違背某些基本的極限。但是這不妨礙我們?nèi)ハ嘈庞?jì)算機(jī)會(huì)比現(xiàn)在快得多,即使它最后只比現(xiàn)在快那么小小的一百萬(wàn)倍,也會(huì)從本質(zhì)上改變編程語(yǔ)言的基本規(guī)則。到那時(shí)候,那些當(dāng)前被認(rèn)為是運(yùn)行速度緩慢、不能生成高效率生成碼的語(yǔ)言就會(huì)得到更多的空間。 固然有一些應(yīng)用還將追求速度。因?yàn)槲覀冇糜?jì)算機(jī)解決的一些問題本身是由計(jì)算機(jī)引起的,比如你要處理的視頻圖像的速率依賴于另一臺(tái)產(chǎn)生視頻圖像的速率。另外還存在一些可以無(wú)限吃掉機(jī)時(shí)的問題,例如圖像描述、加密、仿真等。 如果一些應(yīng)用逐漸降低對(duì)效率的要求,而另一些應(yīng)用繼續(xù)要求占用最新的硬件能提供的所有速度。那么更快的計(jì)算機(jī)就意味著語(yǔ)言必須覆蓋一個(gè)更廣泛的效率范圍。我們已經(jīng)看到了這種事的發(fā)生,一些用新近流行的語(yǔ)言來(lái)實(shí)現(xiàn)的程序如果用幾十年前的標(biāo)準(zhǔn)來(lái)衡量的話,那對(duì)機(jī)時(shí)的“浪費(fèi)”是驚人的。 這不只是發(fā)生在編程語(yǔ)言上的一個(gè)現(xiàn)象,而是一個(gè)普遍的歷史趨勢(shì)。當(dāng)技術(shù)更新?lián)Q代了以后,后一代都能做前一代會(huì)認(rèn)為是浪費(fèi)的事情。三十年前的人肯定會(huì)覺得我們隨心所欲地打長(zhǎng)途電話是件令人驚訝的事,一百年前的人們一定會(huì)更驚訝于從波士頓經(jīng)過孟菲斯到達(dá)紐約的包裹一天就能送到。
我現(xiàn)在就可以告訴你,一百年后當(dāng)我們有了更快的硬件以后那些新增的處理能力都做了些什么?它們都將被“浪費(fèi)”掉! 我從計(jì)算機(jī)能力還很珍貴的時(shí)候開始學(xué)習(xí)編程。我還記得那時(shí)候從我的Basic程序中節(jié)省出所有能節(jié)省的空間以便裝入一個(gè)4K大小的TRS-80,在這個(gè)無(wú)止境的重復(fù)上我花費(fèi)了很大的精力,把機(jī)器的能力發(fā)揮到極限,最終還是受不了這種低效。但是現(xiàn)在看來(lái),我那時(shí)拼命節(jié)約機(jī)器資源的直覺是錯(cuò)誤的——就如同一個(gè)從小受過貧窮的煎熬的人,連去看醫(yī)生這樣很重要的事情也不舍得花錢。 某些浪費(fèi)固然是可恥的,譬如SUVs(譯注:Sport Utility Vehicle,運(yùn)動(dòng)型多功能轎車)就被證明是一種拙劣的產(chǎn)品,即使它載油量很大且不會(huì)產(chǎn)生污染。SUV之所以拙劣,是因?yàn)樗鼮榱私鉀Q一個(gè)拙劣的問題——怎么讓一輛小型貨車看上去更威猛。不過不是所有的浪費(fèi)都是壞的。我們有證據(jù)來(lái)支持這一點(diǎn),打長(zhǎng)途電話的時(shí)候你不會(huì)繁瑣地一分鐘一分鐘地?cái)?shù)時(shí)間,如果有足夠的資源,無(wú)論是打長(zhǎng)途還是短途,你可能會(huì)覺得都是一樣的。 有好的浪費(fèi),也有不好的浪費(fèi)。我對(duì)好的浪費(fèi)感興趣,就是那種花更多的開銷,但是能獲得更簡(jiǎn)單的設(shè)計(jì)。我們?nèi)绾螐睦速M(fèi)更新、更快的硬件的機(jī)時(shí)中獲取好處呢? 在這個(gè)計(jì)算機(jī)處理能力很弱的時(shí)代,對(duì)速度的渴求在我們心中早已根深蒂固,我們應(yīng)該有意識(shí)地克服這種想法。在語(yǔ)言設(shè)計(jì)中,我們應(yīng)該有意識(shí)地尋找一切機(jī)會(huì),用執(zhí)行效率來(lái)?yè)Q取哪怕很小的使用便利性。
大多數(shù)數(shù)據(jù)結(jié)構(gòu)都是由于速度的原因而存在。譬如,當(dāng)今很多語(yǔ)言都既有字符串又有列表(list)。從語(yǔ)義上講,字符串是列表的一個(gè)子集——其元素為字符,因此你為什么需要一種單獨(dú)的數(shù)據(jù)類型呢?真的不需要。字符串的存在,只是因?yàn)樾实脑?。但是這種用擾亂語(yǔ)言語(yǔ)義的手法來(lái)使程序運(yùn)行更快的做法是沒有說(shuō)服力的。語(yǔ)言中包含字符串類型就是一種不成熟的優(yōu)化。 如果我們把語(yǔ)言的核心看成是一組公理集,那么只簡(jiǎn)單地為了效率的好處而往這個(gè)公理集里面添加公理,卻不能增加語(yǔ)言的表達(dá)力的話,這種添加就是丑陋的。效率是很重要,但是我不認(rèn)為那種獲取效率的方法是正確的。 我認(rèn)為解決問題的正確方法是將程序的內(nèi)涵與它的實(shí)現(xiàn)細(xì)節(jié)分離。不要既有列表又有字符串,只要有列表就夠了,如果有必要,可以通過某種方式給編譯器以建議,允許編譯器把字符串按照相鄰字節(jié)來(lái)存放。 既然速度在程序的絕大部分地方都無(wú)關(guān)緊要,那么你通常就不必為這種小事操心了,這一點(diǎn)隨著計(jì)算機(jī)速度越來(lái)越快,將越來(lái)越正確。
人們很少注意到程序的實(shí)現(xiàn)也應(yīng)當(dāng)使程序變得更有彈性。一個(gè)程序往往在編寫的過程中會(huì)發(fā)生需求變化,這是不可避免的,也是應(yīng)當(dāng)受到歡迎的。 “essay”(譯注:企圖;小品文)一詞源于法語(yǔ)的一個(gè)動(dòng)詞“essayer”,意思是“嘗試”,也指為了“試圖”推演出某一結(jié)論而寫的東西。軟件也跟essay一樣,作者往往并不確知哪些才是他們真正要表達(dá)的東西,我認(rèn)為一些最好的程序也是essay。 Lisp(譯注:一種表處理語(yǔ)言,用于處理包含有表格的數(shù)據(jù)的編程語(yǔ)言,被廣泛地運(yùn)用于人工智能研究)黑客(hacker,譯注:黑客指掌握尖端電腦技術(shù)的人,而不是人們常說(shuō)的網(wǎng)絡(luò)入侵者,下同)們已經(jīng)了解到彈性數(shù)據(jù)結(jié)構(gòu)的價(jià)值,我們傾向于在程序的第一個(gè)版本中用列表(list)來(lái)處理一切數(shù)據(jù)。這種最初的版本是如此驚人地低效,因?yàn)樗幸獾乇苊馊ハ胨降滓鍪裁吹募?xì)節(jié),就像——至少對(duì)我來(lái)說(shuō)——是吃牛排的時(shí)候有意避免去想它來(lái)自哪里一樣。 一百年后程序員將需要什么語(yǔ)言?最可能是那種只需要最少的精力就寫出 “非常低效”的“第一版程序”就搞定問題的語(yǔ)言。至少,我們目前可以如此描述這種語(yǔ)言。而用他們的話說(shuō),他們需要一種容易編程的語(yǔ)言。 低效的軟件不是拙劣的,真正拙劣的是使程序員做不必要的工作的語(yǔ)言。浪費(fèi)機(jī)器時(shí)間不是低效,浪費(fèi)程序員的時(shí)間才是真正的低效。這個(gè)道理隨著計(jì)算機(jī)越來(lái)越快,也將會(huì)越來(lái)越明白。
我想去掉字符串(string)這種數(shù)據(jù)結(jié)構(gòu)已經(jīng)指日可待了。我們?cè)?span>Arc(譯注:Lisp的一種方言)中就已經(jīng)是這么做的,而且成功了。一些用正則表達(dá)式描述起來(lái)相當(dāng)拙劣的操作,在Arc中用遞歸函數(shù)就很容易描述了。 像這種扁平的數(shù)據(jù)結(jié)構(gòu)還能存在多久?我審慎而全面地思考了各種可能性,結(jié)果連我都大吃一驚。譬如,我們將會(huì)放棄數(shù)組嗎?畢竟,數(shù)組只是一種以整數(shù)向量為鍵值的哈希表(hash table),而我們會(huì)連哈希表都用列表來(lái)取代嗎? 有的預(yù)測(cè)甚至比這個(gè)更駭人聽聞。譬如McCarthy在1960就描述過的Lisp語(yǔ)言中連數(shù)字(number)都沒有。邏輯上講,你并不一定需要一個(gè)關(guān)于數(shù)字的單獨(dú)的符號(hào),因?yàn)槟憧梢杂昧斜韥?lái)表示數(shù)字,整數(shù)n可以用一個(gè)n個(gè)元素的列表來(lái)表示,你可以用這種方式進(jìn)行數(shù)學(xué)計(jì)算。只不過這樣不堪其低效。 現(xiàn)實(shí)中沒有人被建議用列表來(lái)實(shí)現(xiàn)數(shù)字操作,事實(shí)上McCarthy在1960年的論文在那時(shí)也根本沒有指望被實(shí)現(xiàn)。那只是一項(xiàng)理論探討,只是嘗試給圖靈機(jī)(Turing Machine)創(chuàng)造一種優(yōu)雅的替代。出人意料的是,有人卻根據(jù)那篇文章做出了一個(gè)可工作的Lisp解釋器。不過數(shù)字不是用列表來(lái)表示,而是跟其他語(yǔ)言里一樣,用二進(jìn)制的方式來(lái)表示的。 編程語(yǔ)言會(huì)發(fā)展到去掉數(shù)字這種基本數(shù)據(jù)類型的程度嗎?我這么問不是信口開河地制造聳人聽聞的未來(lái)問題。情況就如同無(wú)堅(jiān)不摧的矛遇到了無(wú)所不克的盾——在這里是無(wú)比低效的代碼遇到了無(wú)比豐富的硬件資源。我認(rèn)為這完全有可能,因?yàn)槲磥?lái)還相當(dāng)長(zhǎng)。如果某種做法可以減少語(yǔ)言的核心公理的數(shù)目,那么它隨著時(shí)光飛逝會(huì)越來(lái)越值得“下注”。如果某種想法在一百年后依然是荒唐的,在一千年后或許未必荒唐。 必須聲明,我并不是建議所有的數(shù)值計(jì)算統(tǒng)統(tǒng)用列表來(lái)實(shí)現(xiàn)。我只是建議語(yǔ)言在沒有為應(yīng)用而增加任何額外的符號(hào)之前的核心部分這樣來(lái)定義。實(shí)際上任何需要數(shù)學(xué)計(jì)算的程序大多會(huì)用二進(jìn)制來(lái)表示數(shù)字,但是這只是一個(gè)優(yōu)化,并在語(yǔ)言的核心語(yǔ)義范圍中。
另外應(yīng)用程序和硬件之間軟件的多層次性也消耗了很多計(jì)算機(jī)機(jī)時(shí)。這也是我們已經(jīng)看到的發(fā)展趨勢(shì):許多軟件只是被編譯成字節(jié)碼,運(yùn)行在字節(jié)碼解釋器上。Bill Woods曾經(jīng)告訴我,每一層解釋器大概最起碼要消耗10%的速度,這些額外的開銷換來(lái)的是你程序的彈性。 Arc的最初版本就是這種軟件分多層以獲取彈性的極端的例子。那是一個(gè)建立在Common Lisp上的經(jīng)典的“元循環(huán)”(metacircular)解釋器,與McCarthy最初的Lisp論文中的eval函數(shù)(eval function)有一定的共同性。整個(gè)Arc只有200余行代碼,所以非常易于理解和修改。而我們所用的Common Lisp,即CLisp本身又運(yùn)行在一個(gè)字節(jié)碼解釋器上。因此這里就存在兩層解釋器,其中一層(上面的那一層)是驚人的低效,但是Arc仍然能用。雖然我承認(rèn)它用起來(lái)很勉強(qiáng),但是畢竟能用。 在應(yīng)用程序方面,把軟件分層是一項(xiàng)了不得的技術(shù)。自底向上編程意味著一層一層地寫程序,每一層作為“語(yǔ)言”供上一層使用。這種方式有利于生成小而靈活的程序,也是取得可復(fù)用性這座“圣杯”(holy grail)的最佳途徑——“語(yǔ)言”定義上的可復(fù)用性。在你寫某種類型的應(yīng)用程序的時(shí)候,越是能把你的應(yīng)用下壓到“語(yǔ)言”中,你的軟件的可復(fù)用性也就越高。 不知何故可復(fù)用性的思想在1980年代被牽扯到面向?qū)ο缶幊讨?,并且看?lái)還沒有要把它解放出來(lái)的反對(duì)性的跡象。然而雖然某些面向?qū)ο筌浖强蓮?fù)用的,但是使程序可復(fù)用的并不是面向?qū)ο?,而是它的自底向上特性。想想?kù)函數(shù):它們可復(fù)用使因?yàn)樗鼈兪恰罢Z(yǔ)言”,無(wú)論它們是不是采用了面向?qū)ο蟮姆椒ā? 順便說(shuō)一句,我并不是預(yù)測(cè)面向?qū)ο缶幊痰臏缤觥km然我認(rèn)為它不能給好的程序員更多的幫助,但是在某些專門的領(lǐng)域,一些大型組織還是離不開它。面向?qū)ο缶幊烫峁┝艘环N可行的方式去獲得意大利面條式的代碼,它允許你把一系列代碼碎片拼合成程序。大型組織通常愿意用這種方式開發(fā)軟件,我認(rèn)為一百年后情況也還是如此。
在我們談?wù)撐磥?lái)的時(shí)候,最好也談?wù)劜⑿杏?jì)算,因?yàn)槟菚r(shí)候這種想法將成為現(xiàn)實(shí)。也就是說(shuō),并行計(jì)算看來(lái)一定會(huì)實(shí)現(xiàn),無(wú)論你說(shuō)那是什么時(shí)候。 未來(lái)能趕上并行計(jì)算嗎?人們近20年來(lái)都在說(shuō)并行計(jì)算即將實(shí)現(xiàn),可是它到如今也還沒有對(duì)編程產(chǎn)生實(shí)質(zhì)影響。真的沒有影響嗎?芯片設(shè)計(jì)者們不得不考慮它,試圖寫在多CPU電腦上的系統(tǒng)軟件的人們也不得不考慮它。 真正的問題在于,并行化會(huì)在抽象的道路上走多遠(yuǎn)?一百年后它會(huì)影響到應(yīng)用軟件的程序員嗎?還是只是編譯器編寫者們才考慮它,而一般應(yīng)用軟件的源代碼里看不見其蹤影? 很有可能的倒是大多數(shù)并行化的機(jī)會(huì)都會(huì)被浪費(fèi)。這是我所作的關(guān)于我們所獲得大多數(shù)額外的計(jì)算能力將會(huì)被浪費(fèi)的預(yù)測(cè)的一個(gè)特例。我認(rèn)為,隨著將來(lái)硬件處理速度的巨大提升,并行化將不會(huì)很常用,除非你確實(shí)需要它。這表明我們一百年后的并行化(除了特定的應(yīng)用以外)都不會(huì)是大規(guī)模的并行化。我認(rèn)為對(duì)普通程序員來(lái)說(shuō),更可能是生成一些并行運(yùn)行的子進(jìn)程。 這就像在程序生命的晚期你改變一個(gè)數(shù)據(jù)結(jié)構(gòu)的精確實(shí)現(xiàn)一樣,你只是在試圖優(yōu)化它。“第一版程序”通常會(huì)忽略并行計(jì)算帶來(lái)的好書,就像忽略數(shù)據(jù)的精確表述帶來(lái)的好處一樣。 因此,除了某些特定的應(yīng)用軟件以外,一百年內(nèi)并行化將不會(huì)普遍在程序里使用。如果用了,將會(huì)是一種不成熟的優(yōu)化。
一百年后將還存在多少種編程語(yǔ)言?最近似乎有大量新的編程語(yǔ)言出現(xiàn)。部分原因是更快的硬件允許程序員們?cè)谒俣群捅憷灾g根據(jù)應(yīng)用做出不同的折中。如果語(yǔ)言的增多是一個(gè)真實(shí)的趨勢(shì),那么一百年后我們擁有的硬件只會(huì)增長(zhǎng)這種趨勢(shì)。 不過也許一百年后只剩下幾種廣泛使用的語(yǔ)言。我這樣說(shuō),部分原因是我的樂觀:如果你真的干得好,你可能設(shè)計(jì)出某種語(yǔ)言,它既適合寫出 “慢而便利”的“第一版程序”,也可以在需要的時(shí)候通過給編譯器一些適當(dāng)?shù)膬?yōu)化建議,讓它產(chǎn)生非??斓纳纱a。因?yàn)槲业臉酚^,我還可以預(yù)測(cè)不管“可接受”的效率與“最高效”的效率之間的 “鴻溝”有多寬,一百年后程序員都將擁有合適的語(yǔ)言跨越它們。 隨著“鴻溝”的變寬,性能評(píng)測(cè)器(profiler)將會(huì)越來(lái)越重要?,F(xiàn)在軟件性能評(píng)測(cè)方面關(guān)注的太少了,許多人都還相信編寫出能產(chǎn)生快的生成碼的編譯器是讓程序運(yùn)行更快的途徑。隨著“可接受性能”與“最優(yōu)性能”之間的“鴻溝”的變寬,人們也越來(lái)越清楚獲得更快的應(yīng)用軟件的正確途徑是要有一個(gè)從“可接受”到“最優(yōu)”的指引,就是性能評(píng)測(cè)器。 當(dāng)我說(shuō)未來(lái)只會(huì)剩余幾種語(yǔ)言的時(shí)候,并不包括那些特定領(lǐng)域的“小語(yǔ)言”。我認(rèn)為這些嵌入式語(yǔ)言是偉大的,我也希望它們能夠越來(lái)越多。但是我希望它們寫出來(lái)的東西能夠像薄薄的外皮一樣,讓用戶能夠看到下面更通用的語(yǔ)言。
誰(shuí)來(lái)設(shè)計(jì)未來(lái)的語(yǔ)言呢?過去十年里一個(gè)最振奮人心的趨勢(shì)是Perl、Python、Ruby等開放源碼語(yǔ)言興起,黑客們接過了語(yǔ)言設(shè)計(jì)的任務(wù)。迄今為止結(jié)果雖然凌亂,但還算可嘉。例如,Perl里面就有一些極好的新穎的想法。雖然也有許多還很不足的地方,但是大家都在執(zhí)著地努力。如果保持現(xiàn)在的轉(zhuǎn)變速度,天知道一百年后Perl會(huì)進(jìn)化成一個(gè)什么樣的語(yǔ)言。 一般來(lái)講可實(shí)踐者也是傳授者(我認(rèn)識(shí)一些最優(yōu)秀的黑客都是教授),但是有許多領(lǐng)域傳授者卻不是實(shí)踐者,所謂“學(xué)術(shù)”一向以堂皇的職業(yè)等級(jí)欺騙視聽。在任何學(xué)術(shù)領(lǐng)域都有一些主題是被認(rèn)可的而另外一些主題卻不是,不幸的是被認(rèn)可的主題與不被認(rèn)可的主題之間的區(qū)別往往在于它在研究論文中的描述聽起來(lái)多么有難度,而不是取得一個(gè)好的結(jié)果的意義有多么重要。像文藝作品就是一個(gè)明顯的例子,研究文藝作品的人很少說(shuō)對(duì)作者哪怕有一丁點(diǎn)用處的話。 雖然在科學(xué)里情況要好一些,但是你可以做的事情很多,可以產(chǎn)生好的語(yǔ)言的事情卻很少,之間的重疊少得可憐。(Olin Shivers曾經(jīng)痛批過這一點(diǎn)。)例如,數(shù)據(jù)類型的研究一直以來(lái)都是研究論文的不竭的題材源泉,但是對(duì)于靜態(tài)類型將要排除宏類型(我認(rèn)為,如果沒有宏,將沒有哪種語(yǔ)言值得使用)的事卻不聞不問。 看當(dāng)前語(yǔ)言發(fā)展趨勢(shì),語(yǔ)言設(shè)計(jì)正在趨于被當(dāng)作開源項(xiàng)目來(lái)開發(fā)而不是當(dāng)作研究課題來(lái)做,而且開發(fā)者也正在趨于編寫應(yīng)用程序的程序員而不是編譯器的編寫者。這是一個(gè)好的趨勢(shì),我希望它繼續(xù)下去。
不像物理學(xué)——幾乎不可能預(yù)測(cè)它一百年后的樣子,我認(rèn)為原則上是可能現(xiàn)在設(shè)計(jì)一種語(yǔ)言符合一百年后的用戶需要的。 可能的設(shè)計(jì)出那種語(yǔ)言的方式是僅憑你的意愿寫下程序,不用考慮是否有編譯器可以解釋它,也不用考慮是否有硬件能運(yùn)行它。當(dāng)你寫程序的時(shí)候你可以假想有無(wú)限的資源(我想我們現(xiàn)在應(yīng)該可以想象得到一百年后有無(wú)限資源的情景)。 人們會(huì)憑意愿寫出什么樣的程序呢?應(yīng)該是所需的最少的勞動(dòng)。要徹底的最少:在你的思維還沒有被你現(xiàn)在習(xí)慣了的編程的語(yǔ)言影響的“前提”下所想到的所需的最少的勞動(dòng)。不過你已經(jīng)習(xí)慣了的編程語(yǔ)言的影響是如此的普遍深刻,以致于你不得不做出巨大的努力來(lái)克服它。你可以盡量想象一下我們這些懶鬼怎么去用最少的努力表達(dá)一個(gè)程序。事實(shí)上,因?yàn)槲覀兯械南敕ㄊ侨绱耸艿轿覀兊乃季S所用的語(yǔ)言的限制,所以程序的簡(jiǎn)潔一點(diǎn)的表達(dá)都讓我們非常吃驚。你需要做的是發(fā)現(xiàn)和覺醒,不是自然而然地陷入其中。 一個(gè)有用的訣竅是用程序的長(zhǎng)度來(lái)作為你編程勞動(dòng)的多少的近似值——當(dāng)然不是按字符來(lái)計(jì)算的長(zhǎng)度,而是按獨(dú)立語(yǔ)法元素(基本上就是是解析樹的大小)來(lái)計(jì)算的長(zhǎng)度。要說(shuō)最短的程序就標(biāo)志是你最少編程勞動(dòng)也不完全準(zhǔn)確,但是它作為一個(gè)簡(jiǎn)潔性的指標(biāo)是寥勝于無(wú)的。那么,語(yǔ)言設(shè)計(jì)的法則就變成了:看看一個(gè)程序并問一問,是否還有別的方法可以把程序?qū)懙酶蹋? 實(shí)際上,用不可想象的百年語(yǔ)言寫程序會(huì)根據(jù)你接近它的內(nèi)核的程度不同其結(jié)果也有所不同。你可以現(xiàn)在就寫出排序程序,但是很難預(yù)測(cè)一百年后將需要什么樣的代碼庫(kù)(library),大概會(huì)出現(xiàn)許多新領(lǐng)域的代碼庫(kù)。譬如,如果到時(shí)候SETI@home(譯注:Search for Extra Terrestrial Intelligence at home,是由美國(guó)加州大學(xué)伯克利分校建立的一項(xiàng)旨在利用連入Internet的成千上萬(wàn)臺(tái)計(jì)算機(jī)的閑置能力搜尋地外文明的巨大試驗(yàn))還有效,我們就將需要與外星人(alien)通信的代碼庫(kù)。當(dāng)然前提是他們也足夠發(fā)達(dá),也能用XML來(lái)溝通。 極端一點(diǎn),我認(rèn)為你今天就有可能設(shè)計(jì)出那種核心語(yǔ)言。有人可能會(huì)說(shuō),實(shí)際上它已經(jīng)早在1958年(譯注:J.McCarthy于1958年提出了Lisp的想法,并于同年跟他的學(xué)生們一起進(jìn)行最初的實(shí)現(xiàn)工作。)就被設(shè)計(jì)好了。
假設(shè)我們今天就可以用所謂百年語(yǔ)言,我們會(huì)用它來(lái)編程嗎?為了回答這個(gè)問題,讓我們回顧一下從前,如果我們當(dāng)前所用的編程語(yǔ)言在1960年就可用,那時(shí)的人們會(huì)用它們嗎? 從各個(gè)方面來(lái)講,答案都是否定的。當(dāng)今的語(yǔ)言是建立在1960年還不存在的一些基礎(chǔ)上的。例如,像Python這種語(yǔ)言中每行的縮進(jìn)是很有意義的規(guī)定,但是這種規(guī)定在那時(shí)候的打印終端上是行不通的。這樣的問題暫且不說(shuō),試想一下,那時(shí)候的程序都是寫在紙上的,1960年代的程序員們會(huì)喜歡用我們今天所用的語(yǔ)言來(lái)寫程序么? 我認(rèn)為還是會(huì)的。雖然對(duì)于那些已經(jīng)把史前古老的語(yǔ)言根深蒂固地融入到他們對(duì)計(jì)算機(jī)程序的認(rèn)識(shí)中的缺乏想象力的人來(lái)說(shuō),確實(shí)很難。(天哪!沒有指針方法那怎么操縱數(shù)據(jù)?沒有g(shù)oto怎么實(shí)現(xiàn)流程圖?)但是我認(rèn)為最聰明的程序員們將很自然地使用我們當(dāng)今所用的大多數(shù)語(yǔ)言——如果他們當(dāng)時(shí)有這些語(yǔ)言的話。 如果我們現(xiàn)在就擁有了百年語(yǔ)言,起碼它會(huì)產(chǎn)生偉大的偽代碼。用它來(lái)寫程序又會(huì)怎么樣呢?既然百年語(yǔ)言需要生成快的生成碼以適應(yīng)某些應(yīng)用,那么大概它應(yīng)該也能生成足夠可接受的高效的生成碼來(lái)適應(yīng)我們現(xiàn)在的硬件。只是我們或許不得不比一百年后的用戶要給出更多的優(yōu)化建議,但那也是劃算的。
我們現(xiàn)在有了兩個(gè)觀念,如果你把他們結(jié)合起來(lái),會(huì)產(chǎn)生有趣的可能性:(1)原則上講,百年語(yǔ)言是可以在今天被設(shè)計(jì)出來(lái)的;(2)這種語(yǔ)言如果今天已經(jīng)存在,那么用它來(lái)編程應(yīng)當(dāng)是不錯(cuò)的。當(dāng)你看到像這樣明擺著的兩個(gè)觀念,就不難想到:為什么不現(xiàn)在就試著用百年語(yǔ)言來(lái)編程呢? 如果你是做語(yǔ)言設(shè)計(jì)工作的,我認(rèn)為你最好有這種目標(biāo),并且把它牢記于心。當(dāng)你學(xué)駕駛的時(shí)候,他們教給你的基本原則之一就是不要只是讓你的引擎蓋對(duì)準(zhǔn)道路上的行道線,而是要把目光瞄準(zhǔn)遠(yuǎn)處。哪怕你只是在意下一個(gè)10英尺會(huì)發(fā)生的事,也應(yīng)該這樣。我想我們?cè)诰幊陶Z(yǔ)言方面可以也應(yīng)該這樣做。
Notes 我相信Lisp語(yǔ)言中的Machine Lisp是第一個(gè)將“聲明(動(dòng)態(tài)變量除外)只是優(yōu)化建議,而不會(huì)改變正確程序的意義”這一原理具體化的語(yǔ)言,而Common Lisp首次將其明確地闡釋了出來(lái)。 感謝Trevor Blackwell,Robert Morris 和Dan Giffin,他們閱讀了本文的初稿,感謝Guido van Rossum,Jeremy Hylton和Python社團(tuán)的其他全體成員,是他們邀請(qǐng)我在Python大會(huì)上講話。
|
|