⑴ 如何閱讀和學習《計算機程序設計藝術(TAOCP)》
哦,上帝!《The Art of Computer Programming》引那位出名的王垠對TAOCP的評論: 本來早就想想寫一個對於Knuth的The Art of Computer Programming的看法。 沒想到一去Amazon就找到一個同類 關於Knuth的 TAOCP,我想,大部分人聲稱看了他的書,或者買了他的書,不過是作為一種炫耀的資本或者擺設。我對門的同學幾年前就買了一套三本,全新的精裝本,花了 200多塊錢。可是呢,他從來就沒看。我把它借過來,看了幾頁就放在那裡沒有看了。我哪有時間看他用那些一個位元組6位的機器語言實現簡單的鏈表!有一天一個師弟走進來,看到那套書在我書架上,顯示出一種敬畏感:「挖!師兄!你好牛啊!居然看這么高深的書!」 我一愣。嗯,不錯嘛,這套書放在書架上可以讓人對我刮目相看。這恐怕就是它對很多人的實際作用。還有人可以幫助神化這套書,同時也神化自己,比如他可以這么說:「誰要是看完了Don Knuth的 The Art of Computer Programming 我就僱用他!」 這樣可以顯得比一般看過書的人還要高一等。據說Bill Gates就是這么做的。我懷疑他自己看完過沒有。 我討厭這套書的一個原因就是Knuth故意用一個叫 MIX 的處理器的機器語言來寫這本書。雖然在新版的書里他設計了一種新的處理器 MMIX,但是換湯不換葯。他以為一部「永恆」的計算機編程書不應該使用高級語言,因為它們很容易過時。但是他錯了,機器語言恰恰是最容易過時的東西,看看現在有多少牌子的更新換代的處理器就知道。而世界上確實存在非常高級的語言從60年代到現在都沒有過時。我預言,MMIX會在不久的將來被淘汰。很好笑的是MMIX是在MIX上加了一個「M」,代表Millennium(千禧年)。關於它的專著也起名為 MMIXware---A RISC Computer for the Third Millennium。一千年甚至短短一百年,幾十年以後,計算機還是不是二進制的集成電路都說不清楚,況且這個處理器其實就是從別的處理器比如RISC II, Sparc之類的撿了一點東西,沒有什麼大的創新。他就把這個處理器的模擬程序印在紙上賣,曰:「一個優秀的程序要像一部好的小說一樣容易讀懂。一個優秀的程序員會在將來拿到普利策獎。」 用機器語言寫一點初級的計算機入門部分還可以,但是用來寫整整一部書未免容易讓讀者只見樹木不見森林了。看TAOCP最容易出現的一種現象就是,「哇!原來這個程序可以這么寫。」 但是你不知道為啥那麼寫。雖然可以知道一些底層的原因,但是最根本的原理,讀者始終不會明白。就像看清楚了一張圖片上的每一個像素,卻認不出圖片上其實是一個熟人。看清楚了棋盤上每一個棋子能走的地方,卻不能贏棋。Dijkstra 說計算科學不應該被叫做"computer science",就像外科手術不應該叫做"knife science"。可是這關Knuth什麼事呢,他的書名叫做 The Art of... 再說他的支票吧…… 很多人拿了Knuth的支票就作為一種可以炫耀的東西。以前我就看到一個Cambridge的教授主頁上掛著一個Knuth支票的照片。Knuth的支票真的可以作為炫耀的資本嗎?告訴你們,我找到的錯誤都是typo而已,沒想到他也給我支票。誰叫他打字不小心,Millennium都能打成 Millenium?嘿!我湊足了一頓飯錢的支票時就想去中國銀行兌現,准備換了錢大吃一頓。可是銀行的職員告訴我,他們必須把支票寄回美國才能拿到現金,辦理這件事的費用大大高於支票本身的價值!所以Knuth相當於給我一些空頭支票。Damn!早該想到的,他為什麼不往大家的信用卡上面轉賬,而使用支票這種過時的東西!他明顯覺得有他簽名的支票,肯定誰也不會拿去兌現,甚至裝裱在相框里作為紀念。hmmm... 算你狠~ 好了,啰里啰唆。還是看看這個別人寫的書評。White elephant,這確實道出了我對這套書的感覺。 (但是評價者有些觀點我不能苟同,比如「O(n)表示法足夠了」。) 希望以後對 paper 也有這種公開的 comments! Dan Friedman 的故事 (4)——C311當我剛從 Cornell 轉學到 IU 的時候,Dan Friedman 叫我去上他的研究生程序語言課 B521。我當時以自己在 Cornell 上過程序語言課程為由,想不去上他的課。Friedman 把我叫到他的辦公室,讓我在他旁邊坐下來,和藹的對我說:「王垠,我知道你在 Cornell 上過這種課。我也知道 Cornell 是比 IU 好很多的學校。可是每個老師的教學方法都是不一樣的,你應該來上我的課。我和我的朋友們在這里做教授,不是因為喜歡這個學校,而是因為我們的家人和朋友都在這里。」後來由於跟 Amr Sabry(我現在的導師)的課程 B522 時間重合,他特別安排我坐在本科生的 C311 的課堂上,卻拿研究生課程的學分。後來發現,這兩門課的內容基本沒有區別,只不過研究生的作業要多一些。 在第一堂課上,他說了一句讓我記憶至今的話:「《The Little Schemer》和《Essentials of Programming Languages》是這門課的參考教材,但是我上課從來不講我的書里的內容。」剛一開始,我就發現這門課跟我在 Cornell 學到的東西很不一樣。雖然有些概念,比如 closure,CPS,我在 Cornell 都學過,在他的課堂上,我卻看到這些概念完全不同的一面,以至於我覺得其實我之前完全不懂這些概念!這是因為在 Cornell 學到這些東西的時候只是用來應付作業,而在 Friedman 的課上,我利用它們來完成有實際意義的目標,所以才真正的體會到這些概念的內涵和價值。 一個例子就是課程進入到沒幾個星期的時候,我們開始寫解釋器來執行簡單的 Scheme 程序。然後我們把這個解釋器進行 CPS 變換,引入全局變數作為"寄存器" (register),把 CPS 產生的 continuation 轉換成數據結構(也就是堆棧)。最後我們得到的是一個抽象機 (abstract machine),而這在本質上相當於一個真實機器里的中央處理器(CPU)或者虛擬機(比如 JVM)。所以我們其實從無到有,「發明」了 CPU!從這里,我才真正的理解到寄存器,堆棧等的本質,以及我們為什麼需要它們。我才真正的明白了,馮諾依曼體系構架為什麼要設計成這個樣子。後來他讓我們去看一篇他的好朋友 Olivier Danvy 的論文,講述如何從各種不同的解釋器經過 CPS 變換得出不同種類的抽象機模型。這是我第一次感覺到程序語言的理論對於現實世界的巨大威力,也讓我理解到,機器並不是計算的本質。機器可以用任何可行的技術實現,比如集成電路,激光,量子,分子,基因…… 但是無論用什麼作為機器的材料,我們所要表達的語義,也就是計算的本質,卻是不變的。 而這些還不是我那屆 C311 全部的內容。後半學期,我們開始學習 miniKanren,一種他自己設計的用於教學的邏輯式語言 (logic programming language)。這個語言類似 Prolog,但是它把 Prolog 的很多缺點給去掉了,而且變得更加容易理解。教材是免費送給我們的《The Reasoned Schemer》。在書的最後,兩頁紙的篇幅,就是整個 miniKanren 語言的實現!我學得比較快,後來就開始搗鼓這個實現,把有些部分重新設計了一下,然後加入了一些我想要的功能。這樣的教學,給了我設計邏輯式語言的能力,而不只是停留於一個使用者。這是學習 Prolog 不可能做到的事情,因為 Prolog 實現的復雜性,會讓初學者無從下手,只能停留在使用者的階段。 我很幸運當初聽了他的話,去上了這門課,否則我就不會是今天的我。 誰是真正的程序語言專家Knuth 也曾有類似的說法:「要是看不懂 TAOCP,就別當程序員。」他總是被譽為「計算機科學的神」,在他的演講里大談文學,藝術,上帝和宗教,給人陡增神秘感。他總是說程序員應該學習機器語言,而不是高級語言,機器才是不變的真理。但是 Knuth 卻不是從科學的角度來看這個問題,而只是他個人的偏見。當他看到 Fortran, Lisp, ALGOL, Pascal, C, C++, Java 這些語言的發展彷彿沒有盡頭的時候,他並沒有理解其中不變的原理。在程序語言的設計上,他不是一個強者。他很有可能根本不理解 lambda calculus 和類型理論,否則他不會設計出像 TeX 那樣毫無章法的語言。TeX 排版的質量無可厚非,但是到了1978年還仍然採用程序語言專家們早已深惡痛絕的 dynamic scoping,再加上其它一些蹩腳的設計,說明他對程序語言理論缺乏理解。實際上 TeX 含有一個圖靈完備的擴展語言,是因為 Knuth 採納了 Guy Steele(Scheme 的發明者)的建議,然而 Knuth 卻沒有把它設計好。 Knuth 覺得機器是不變的真理,所以他堅持用機器語言來寫作 TAOCP。但是由於機器語言缺乏抽象,程序員沒法專注於真正的問題。使用機器語言來描述演算法,會把本來很簡單的問題都顯得高深難懂,彷彿這書永遠也看不完。有多少人真正的看過 TAOCP 呢?恐怕大部分人把這套書買回去,只是把它們擺在書架上做面子。只要有人說機器語言太難懂,這些人就會說你自己不夠聰明,不配做程序員。而其實呢,他們自己都沒看過。 機器不是計算的本質這個事實,很多人包括 Dijkstra,早就看到了。他說:「計算機科學是個錯誤的名字,因為它不是計算機的科學,這就像外科手術不是刀子的科學。」而這是幾乎每一個程序語言專家都明白的道理。在他們的眼裡,這不再是道聽途說或者個人觀點,而是可以用邏輯來證明的事實。真正明白計算本質的人,可以設計出全新的硬體來來滿足語義的需要,而不是受控於處理器的設計。他們甚至可以超越集成電路,而使用另外的技術來製造機器。這些都說明,計算其實是獨立於機器的。 有不好的想法不要緊,但是如果把不好的想法硬說成是好的,那就會阻礙歷史發展了。我並不否認 Knuth 和 Ritchie 對演算法,排版和操作系統的重要貢獻,但是由於他們以及他們崇拜者經常在有關語言的事情上誤導群眾,所以覺得有必要指出他們的一些局限性。Linus Torvalds, Guido van Rossum, Eric Raymond, Paul Graham 也經常發表對語言的評論,被很多人奉為聖旨,但其實他們言論裡面很少有真知灼見。 其實我要說的不過是,通常程序員們膜拜的偶像,大部分都不是真正的程序語言專家。希望你不要覺得這是危言聳聽,實際上這些是大部分世界級的計算機科學家們很多年前就知道的事情。
⑵ 璁$畻鏈虹▼搴忚捐¤壓鏈路鍗1:鍩烘湰綆楁硶鍐呭圭畝浠
銆婅$畻鏈虹▼搴忚捐¤壓鏈銆嬬郴鍒楋紝鐗瑰埆鏄鍗1錛氬熀鏈綆楁硶錛堣嫳鏂囩増絎3鐗堬級錛屾槸璁$畻鏈虹戝﹀拰璁$畻鏁板﹂嗗煙鐨勫疂璐靛弬鑰冭祫鏂欍傛棤璁轟綘鏄璁$畻鏈虹戝︾殑涓撲笟浜哄憳錛岃繕鏄鍦ㄩ珮鏍′粠浜嬬浉鍏蟲暀瀛︾殑甯堢敓錛岃繖鏈涔﹂兘鑳戒負浣犳彁渚涙繁鍏ョ悊瑙h$畻鏈虹畻娉曠殑鍏抽敭鐭ヨ瘑銆傚畠琚瑙嗕負璁$畻鏈虹戝﹂嗗煙鐨勭粡鍏鎬箣浣滐紝瀵圭▼搴忚捐$悊璁虹殑闃愯堪璇﹀敖涓斿叏闈錛屽硅$畻鏈洪嗗煙鐨勮繘姝ヨ搗鍒頒簡娣辮繙鐨勫獎鍝嶃
璇ヤ功鐨勫嵎1鐗瑰埆鍏蟲敞鍩虹錛屼粠鍩烘湰姒傚康鍑哄彂錛岄愭ュ紩瀵艱昏呮帉鎻℃牳蹇冪畻娉曘傚畠璇︾粏鎺㈣ㄤ簡淇℃伅緇撴瀯錛岃繖浜涢兘鏄鍚庣畫絝犺妭鍜屼笓涓氬彂灞曚腑鐨勫熀鐭熾傚煎緱涓鎻愮殑鏄錛屼功涓榪橀厤浠ヤ赴瀵屽氭牱鐨勪範棰樺拰璇﹀敖絳旀堬紝涓哄︿範鑰呮彁渚涗簡瀹炶返涓庣悊璁虹浉緇撳悎鐨勫︿範璺寰勶紝浣垮叾鍦ㄥ疄璺典腑鐞嗚В鍜屾帉鎻″熀鏈綆楁硶銆
濡傛灉浣犳復鏈涙繁鍏ョ悊瑙h$畻鏈虹▼搴忚捐$殑濂ョ橈紝鎴栬呭笇鏈涘湪鏁欏︿腑寮曞叆鏇存繁鍏ョ殑鐞嗚猴紝閭d箞銆婅$畻鏈虹▼搴忚捐¤壓鏈?鍗1:鍩烘湰綆楁硶(鑻辨枃鐗?絎3鐗)銆嬫棤鐤戞槸浣犵殑鐞嗘兂閫夋嫨錛屽畠灝嗘槸浣犵悊瑙e拰鎺㈢儲璁$畻鏈虹戝︿箣鏃呯殑閲嶈佷竴姝ャ