本文是Common Lisp專家Peter Seibel對計(jì)算機(jī)科學(xué)家Guy Steele的訪談,談到了他程序人生開啟的歷程以及程序員成才的關(guān)鍵。 初涉編程 Seibel:你是怎樣接觸編程的? Steele:嗯,當(dāng)我還是個小學(xué)生時,我就已經(jīng)深深迷戀科學(xué)和數(shù)學(xué)了,我讀了很多這方面的書,比如Irving Adler的Magic House of Numbers,它是我的最愛。我也喜歡兒童科幻小說,比如DanngDunn系列等等。總的來說,我對科學(xué)和數(shù)學(xué)有著廣泛的興趣。所有我能找到的關(guān)于科學(xué)和數(shù)學(xué)的東西,我都讀了,同時我也讀到了一點(diǎn)關(guān)于即將到來的新奇的計(jì)算機(jī)的介紹。 Seibel:你編寫的第一段有趣的程序是什么? Steele:嗯,我首先學(xué)習(xí)了Fortran語言,不過在我開始學(xué)習(xí)IBM 1130匯編語言之后,事情才變得真正有趣。我能想起來的最早的有趣的程序是一段能產(chǎn)生上下文關(guān)鍵字索引的東 Seibel:你在MIT很自在,但最終卻還是去了哈佛讀書,而同時又在MIT打工,這是怎么回事呢? Steele:我申請大學(xué)的時候,申請了三所學(xué)校,MIT、哈佛還有普林斯頓。我最想去的是MIT。三所學(xué)校同時都錄取了我。波士頓拉丁學(xué)校的校長Wilfred L.O’Leary是個老派的學(xué)者。老先生人非常好,打電話給我父母說:“你們知道令郎拿著哈佛的通知書實(shí)際上卻考慮去MIT嗎?”他就這樣向我父母施壓,我父母轉(zhuǎn)而對我施壓,最終我決定去哈佛了。 我父母繼續(xù)找我的麻煩,讓我去打一份夏季工,而不是在家待著——你知道,做父母的都會這樣。我很清楚自己的興趣是計(jì)算機(jī),我可不想去快餐店擺弄漢堡包。我面試了打孔工的工作,并且自以為是完全能夠勝任的。但是沒有人愿意雇用我,部分原因是我還不滿18歲,可找到后才明白。他們聽了我的敘述后說:“不要打電話給我們,我們會打給你的?!比缓缶丸脽o音信了。 大約7月初我聽說MIT的BillMartin正在尋找Lisp程序員。我想:“啊哈,機(jī)會來了,我了解Lisp啊?!蔽疫^去經(jīng)常出沒于MIT的時候,從AI實(shí)驗(yàn)室搞到了一些Lisp文檔的副本,我也曾偷偷溜進(jìn)實(shí)驗(yàn)室擺弄過計(jì)算機(jī)。那些日子里實(shí)驗(yàn)室大門是敞開的,反越戰(zhàn)抗議發(fā)生后門才被鎖上。我在高中四年級時在IBM1130計(jì)算機(jī)上實(shí)現(xiàn)過我自己的Lisp程序。 于是,我這個不知道哪里冒出來的小瘦猴兒,跑到BillMartin的辦公室,從門口探進(jìn)頭說:“我聽說你在招Lisp程序員?!彼]有嘲笑我,只是打量了我一下,然后說:“你得先做做我出的Lisp考題?!薄皼]問題,現(xiàn)在考怎么樣?”我就坐了下來,花了兩個小時來答題。完成后我把試卷遞給他,他用了十分鐘瀏覽了一遍,然后對我說:“你被錄取了?!?/p> 編程導(dǎo)師 Seibel:在你起步時有沒有遇到對你很重要的導(dǎo)師呢? Steele:在拉丁學(xué)校期間我的數(shù)學(xué)老師對我的適當(dāng)鼓勵刺激很重要。9年級的RalphWellings,就是在那個感恩節(jié)周末借我書的那位老師,和我做了一個交易。他說:“我注意到你在所有數(shù)學(xué)測驗(yàn)中都得到了100分。我可以讓你在每周的前4天數(shù)學(xué)課都待在計(jì)算機(jī)室,不過在第5天數(shù)學(xué)課的測試上你必須得到100分,否則,交易就自動終止。”看,這就是激勵。在那年余下的時間中我變成了考試高手——我特別刻苦地學(xué)習(xí)數(shù)學(xué),因?yàn)檫@能讓我接觸到計(jì)算機(jī)。更好的是,第二年我的數(shù)學(xué)老師沒有與我做同樣的交易,這正好,因?yàn)槲覍δ且荒甑臄?shù)學(xué)了解不多。他們做出了恰當(dāng)?shù)脑u估。我的老師都是非常好的老師,我要學(xué)什么他們總是為我大行方便。 Seibel:在那之后,隨著你更深入地學(xué)習(xí)計(jì)算機(jī),有沒有特別的人在這領(lǐng)域幫助你呢? Steele: 有,當(dāng)然就是雇用我的Bill Martin。還有Joel Moses,他領(lǐng)導(dǎo)著Macsyma項(xiàng)目,我受雇于MIT期間就在這個項(xiàng)目組里。 Seibel:在整個大學(xué)期間,你一直在做這個項(xiàng)目嗎? Steele:是的,我在哈佛讀書的時候就一直是MIT的一名雇員。在暑假時是一份全職工作,開學(xué)后它就變成了一份下午的兼職工作。我盡可能地把哈佛的課程安排到早上,這樣我就可以搭乘地鐵去MIT,用兩三個小時來編程,然后再回去。 Seibel:一直用Lisp做Macsyma項(xiàng)目嗎? Steele:是的。具體說就是當(dāng)Maclisp解釋器的維護(hù)人員。Jon L.White原本同時負(fù)責(zé)解釋器和編譯器的工作。他后來成為了一位相當(dāng)厲害的編譯器大師,而我則負(fù)責(zé)解釋器,這個分工不錯。就這樣,Jon L.White成了我的導(dǎo)師。Macsyma項(xiàng)目組里所有的人都很關(guān)照我。我也得以結(jié)識一些AI實(shí)驗(yàn)室的人,所以當(dāng)我申請讀MIT的研究生的時候,很容易就被錄取了,因?yàn)樗麄円呀?jīng)了解我,并且知道我在干什么。 Seibel:你得到了計(jì)算機(jī)科學(xué)學(xué)士學(xué)位? Steele:是的,我本來打算主修純數(shù)學(xué),并且都安排好了我的課程。后來發(fā)現(xiàn)我對什么無窮維巴拿赫空間完全沒有感覺,簡直要害死我了。幸好,我已經(jīng)在業(yè)余時間學(xué)習(xí)了足夠多的計(jì)算機(jī)課程,這讓我可以在專業(yè)的時候很主動。確切地說,我轉(zhuǎn)去修應(yīng)用數(shù)學(xué)專業(yè),而計(jì)算機(jī)科學(xué)是應(yīng)用數(shù)學(xué)的一個分支,在哈佛應(yīng)用數(shù)學(xué)又屬于工程學(xué)的一部分。 Seibel:如果有可能讓你重新學(xué)習(xí)編程,你會有什么不同嗎?有什么事情你希望更早一點(diǎn)完成的嗎? Steele:并不是一開始在我的腦海里就有特定的目標(biāo)。我對我選擇的這條路也不后悔?;厥淄拢蚁胛沂且粋€幸運(yùn)兒,受惠于一系列有趣的巧合,或者說,恩賜。 現(xiàn)在我意識到,實(shí)際上同時在MIT和哈佛的經(jīng)歷是很不尋常的。我可以跑來跑去,然后說:“這條河(編者注:哈佛大學(xué)與MIT只有一河之隔,即查爾斯河)那一邊的教授是這樣說的?!倍@一邊的教授就會說:“哦,別信他,你應(yīng)該這么想?!边@很快讓我的視野更開闊。 作為高中生就能進(jìn)入MIT是另一個相當(dāng)不尋常的經(jīng)歷。我15歲時就可以擺弄那些價值數(shù)百萬美元的機(jī)器,在那時1百萬元可真是一筆相當(dāng)大的錢。所以,我當(dāng)然沒有抱怨,沒有后悔,也不會有任何得隴望蜀的想法。我本性也是個隨遇而安的,既來之,則安之。 Seibel:與那時相比,對于編程的思維方式,有哪些大的改變?除了認(rèn)識到冒泡排序不是最好的排序算法之外。 Steele:我想對我來說,最大的變化是認(rèn)識到你不可能了解運(yùn)行在你計(jì)算機(jī)上的所有一切。有些事情絕對超出了你的控制,因?yàn)椴豢赡芰私馑熊浖囊磺屑?xì)節(jié)。而在上世紀(jì)70年代計(jì)算機(jī)僅僅有4K字節(jié)的內(nèi)存,你完全可以做一個內(nèi)存轉(zhuǎn)儲,然后一個字一個字地去檢查是不是你期望的。閱讀操作系統(tǒng)的源碼,了解它是如何運(yùn)行的自然也正常。我也確實(shí)這樣干過——我研究過磁盤管理程序和卡片閱讀機(jī)程序,然后實(shí)現(xiàn)了我自己的版本。我覺得我自己了解整個IBM 1130是如何運(yùn)作的,或者至少可以說我了解我自己想了解的所有事情。不過現(xiàn)在你再也不能這樣干了。 編程參考書 Seibel:在你學(xué)習(xí)編程的時候,有沒有什么書對你特別重要? Steele:在70年代的書當(dāng)然是Knuth的TAOCP《計(jì)算機(jī)程序設(shè)計(jì)藝術(shù)》。 Seibel:你從頭到尾地讀過嗎? Steele:差不多每頁都讀過,差不多。我做了幾乎所有我能做的習(xí)題。一些被稱作是高等數(shù)學(xué)之類的東西我不太明白,我做了些注釋或跳過了那些我不懂的。不過頭兩卷和第三卷的大部分我都很認(rèn)真地讀過。還有Aho、Hopcroft和Ullman編著的那本算法書(編者注:是指The Desing and Analysis of Computer Alogorithms(《算法分析與設(shè)計(jì)》)一書)——我想我是從這里面真正學(xué)到如何排序的。我得從我的書庫里查找一下,看看能不能還記得有什么別的書。我是個收集狂——這類書我都有。不過這兩本是我首先想到的。還有Lisp的書。Berkeley和Bobrow編輯的III Lisp(編者注:III指IntformationInternational,Inc.):是主題各異的論文集,不過我從中學(xué)到了很多有意思的東西。然后我開始讀《SIGPLAN公報》和《ACM通訊》。那些日子里的《ACM通訊》可是有很多真正的技術(shù)內(nèi)容,非常值得一讀。 我要提及兩件事。第一件,當(dāng)我在拉丁學(xué)校開始對科學(xué)感興趣的時候,我決定從事計(jì)算機(jī)科學(xué)相關(guān)的事情。有一天有個導(dǎo)師問我:“你考慮過成為ACM的學(xué)生會員嗎?”我不知道他的名字。不過我從那時起就非常感謝他,這給了我很大的鼓勵。 而我上哈佛以后,每當(dāng)早晨有點(diǎn)空閑時間,我就會去Lamont圖書館做兩件事:按照我的方式,從后往前閱讀《科學(xué)美國人》,或者從前往后閱讀《ACM通訊》。對《科學(xué)美國人》,我特別注意MartinGardner的所有數(shù)學(xué)游戲?qū)?。對《ACM通訊》則閱讀所有我感興趣的文章。在1972年這本期刊還只有15年的歷史,所以不難把它們?nèi)慷歼^一遍。 Seibel:閱讀所有文章在那時比在今天要容易得多,一個人還是希望了解整個領(lǐng)域的。 Steele:是的,你有希望了解這個領(lǐng)域。有很多只有一頁長短的文章,讓你知道:“這兒有一項(xiàng)新的散打技術(shù)?!蔽易x了很多這類的文章。 Seibel:舊的文章我個人常常覺得不太容易理解,因?yàn)樗鼈兒鸵恍┡f硬件或者舊語言聯(lián)系得比較緊密。 Steele:是這樣的,需要是創(chuàng)新之母——一個想法的出現(xiàn)是因?yàn)樵谝粋€特定的環(huán)境下需要它。過了一段時間,大眾認(rèn)識到這個想法很重要。然后你需要擺脫環(huán)境的局限,展現(xiàn)出核心思想本身凸顯出來,這樣就可以流行好幾年了?!斑@個神奇的技巧可以按位逆轉(zhuǎn)字?!彼麄兘o出了7090匯編語言的一些東西。有些很有趣的數(shù)學(xué)思想在里頭,不過他們還不能從中抽象出來。 Seibel:的確很多人從學(xué)校里開始,在指導(dǎo)下學(xué)習(xí)計(jì)算機(jī)科學(xué)知識。但是還有很多程序員是沒有正規(guī)學(xué)歷背景的,只是邊干邊學(xué)。對這個你有什么建議嗎?你怎么開始閱讀那些技術(shù)論文,如何抓住要點(diǎn)并理解它呢?應(yīng)該從ACM最初讀起,一直讀到現(xiàn)在嗎? Steele:嗯,首先,我得說通讀《ACM通訊》并不是我刻意博覽群書成為一名偉大的計(jì)算機(jī)科學(xué)家的計(jì)劃。我閱讀是因?yàn)槲矣信d趣,有內(nèi)在的動力去學(xué)習(xí)那些資料。所以我覺得這里有兩個因素:第一是有內(nèi)在的動力,想要閱讀它們,因?yàn)槟阌信d趣或者說你覺得能提高你的技能。 另一個問題是你怎樣才能發(fā)現(xiàn)好的東西?當(dāng)然,對“好”的認(rèn)識也是三十年河?xùn)|,三十年河西。今年你覺得是真正好的十年后說不定過時了。我覺得你可以拜訪一位曾經(jīng)經(jīng)驗(yàn)豐富的前輩,問他覺得什么才是好的東西。對我而言就是Knuth,就是Aho、Hopcroft和Ullman。還有GeraldWeinberg《程序設(shè)計(jì)心理學(xué)》,那本書今天還是非常值得讀一讀的。Fred Brook的《人月神話》也給我一些啟示。 那時候我流連于MIT書店的計(jì)算機(jī)科學(xué)書架,下決心每個月到那里去一次,去翻翻那些書架。今天你再去一個書店,它的計(jì)算機(jī)書架規(guī)模可能是那時的10倍了,不過其中大部分圖書都是如何使用C或者Java的。但還是會有一部分理論背景、算法這類書。 代碼閱讀 Seibel:另一種閱讀——我知道你認(rèn)為很重要的——是代碼閱讀。你是怎么樣以你的方式切入不是你編寫的一大段代碼的呢? Steele:如果那個軟件我知道如何使用,但不了解內(nèi)部的工作機(jī)制,我通常會選擇一個特定的命令或者交互行為然后追蹤下去。 Seibel:執(zhí)行路徑嗎? Steele:是的。如果我要開始閱讀Emacs源代碼的話,我會說:“讓我們看看‘向前移動一個字符’的那部分代碼吧?!奔词刮也荒芡耆斫?,我至少會知道它使用的一些數(shù)據(jù)結(jié)構(gòu)以及緩沖區(qū)是怎么表示的。如果我足夠幸運(yùn),我能找到緩沖區(qū)增加一個的地方。一旦我理解之后,我接下來會嘗試“后退一個字符”、“刪除一行”。通過我的方式就了解越來越多的使用方法或者交互,直到我覺得我能夠按照這種方式追蹤代碼的其他更重要的部分。 Seibel:“追蹤”是指查看源代碼在心里執(zhí)行它呢,還是要在調(diào)試器中啟動它,然后單步執(zhí)行進(jìn)去呢? Steele:兩種方式我都會做,我會用單步調(diào)試器對付那些70年代或者80年代的小一點(diǎn)的程序。今天的問題是從啟動程序到它真正可以做點(diǎn)什么,這中間有一段很長的初始化過程。所以更好的辦法是找到主命令循環(huán)或者中央控制子程序,從那里開始追蹤。 Seibel:當(dāng)你找到了那些以后,你是設(shè)置一個斷點(diǎn)然后單步跟進(jìn)去呢,還是僅僅在腦海中想象它們的執(zhí)行過程? Steele:我更愿意做桌面檢查——就是閱讀代碼想象它會做什么。如果我確實(shí)需要理解整段代碼,我會坐下來試圖按照我的方式來通讀代碼。不過你不能一上來就這樣做,應(yīng)該先在腦子中有了事情的組織框架。現(xiàn)在,如果你足夠幸運(yùn),程序員會留下一些文檔或者規(guī)則的命名,或者合理組織文件的順序,方便你快速閱讀他們的代碼。 合理組織文件的順序 Seibel:什么是合理組織文件的順序? Steele:很好的問題。使我想起了諸如Pascal這樣的程序語言的一個問題,Pascal是為只過一遍的編譯器設(shè)計(jì)的,源文件中的過程傾向按照自底向上的方式組織,因?yàn)樵谑褂眠^程之前你必須定義過它們。也就是說,閱讀Pascal程序最好的方法實(shí)際上是從后面讀起,因?yàn)檫@樣你就會看到程序自頂向下的結(jié)構(gòu)?,F(xiàn)在(編譯器)形式如此多樣,你也就不能指望什么了,除非程序員有一顆很強(qiáng)的責(zé)任心,將一切事情安排得井井有條,有助理解。不過,第三點(diǎn),我們現(xiàn)在也有很棒的IDE來幫助你查看交叉引用,也許程序的線性組織也不再是那么重要了。 第四點(diǎn),我個人非常不喜歡IDE的一個原因是,你看完了所有內(nèi)容后,還是很難理解。在圖形迷宮里亂竄,很難知道所有地方都走到了。但如果你得到的是線性順序,就會確保所有事情都會梳理到。 Seibel:那么在你寫代碼的這些日子里,你是不是盡量按照自頂向下來組織代碼呢?高層函數(shù)出現(xiàn)在它們依賴的低層函數(shù)之前? Steele:我盡量表現(xiàn)高層的想法。最好的表現(xiàn)方法可能是展示一個中心的命令,控制的過程,以及向下面分發(fā)的事情。或者,重要的事情可能是首先要展現(xiàn)數(shù)據(jù)結(jié)構(gòu),或者說較重 在MIT工作時,一件很棒的事情是可以隨意訪問到?jīng)]有加密的代碼,它們?nèi)欠浅B斆鞯暮诳妥髌?。于是我讀過了ITS操作系統(tǒng),也讀過了TECO的實(shí)現(xiàn)和Lisp的實(shí)現(xiàn)。還有第一個相當(dāng)漂亮的Lisp格式打印程序,是BillGosper編寫的。事實(shí)上,我在讀高中的時候就讀過它們,還試圖復(fù)制一些到我個人的1130實(shí)現(xiàn)當(dāng)中。 如果沒有接觸到在其他機(jī)型上的現(xiàn)有Lisp實(shí)現(xiàn),我一定不能為1130實(shí)現(xiàn)Lisp的,我根本就不知道怎么做。這是我個人教育的一個很重要的部分。時至今日,我們面對的部分問題是軟件已經(jīng)變得很有價值了,大部分軟件都是商用的,也就是說我們不再有可作為免費(fèi)例子的優(yōu)秀代碼來參考了。開源運(yùn)動在某種程度上扭轉(zhuǎn)了這一點(diǎn)。如果你愿意,你可以深入閱讀Linux的代碼。在我那個時候閱讀TeX的代碼是一項(xiàng)很有意義的練習(xí),因?yàn)樗且淮髩K良好組織的、易于調(diào)試的代碼。 本文節(jié)選自人民郵電出版社北京圖靈文化發(fā)展有限公司出版的《編程人生》一書。該書是當(dāng)今15位大師級計(jì)算機(jī)程序員的訪談錄,重點(diǎn)介紹了他們的編程感悟。特此感謝圖靈公司授權(quán)。 |
|