1. 程式人生 > >讀書筆記 -- 計算機程序的構造和解釋

讀書筆記 -- 計算機程序的構造和解釋

一段時間 常常 因此 過程 一個 層次 最大 art 處理

Structure and Interpretation of Computer Programs

“每一位嚴肅的計算機科學家都應該閱讀這本書。由於本書清晰,簡潔和富於才智,我們強烈推薦這本書。它適合所有希望深刻理解計算機科學的人們。” —— Mitchell Wand 《美國科學家》 “帶著崇敬和贊美,將本書獻給活在計算機裏的神靈。” “我認為,在計算機科學中保持計算中的趣味性是特別重要的事情。這一學科在起步時飽含著趣味性。當然,那些付錢的客戶們時常覺得受了騙。一段時間之後,我們開始嚴肅的看待他們的抱怨。我們開始感覺到,自己真的像是要負起成功的,無差錯的,完美的使用這些機器的責任。我不認為我們可以做到這些。我認為我們的責任是去拓展這一領域,將其發展到新的方向,並在自己的家裏保持趣味性。我希望計算機科學的領域絕不要喪失其趣味意識。最重要的是,我希望我們不要變成傳道士,不要認為你是兜售聖經的人。世界上這種人已經太多了。你所知道的有關計算的東西,其他人也都能學到。絕不要認為似乎成功計算的鑰匙就掌握在你的手裏。你所掌握的,也是我認為並希望的,也就是智慧:那種看到這一機器比你第一次站在它面前時能做得更多的能力,這樣你才能將它向前推進。” ——Alan J. Perlls (1922.4.1 - 1990.1.7) 序 有關於計算機程序具體是關於什麽的,服務於哪類應用等等的情況常常並不重要,重要的是它們的性能如何,在用於構造更大的程序時能否與其他程序平滑銜接。程序員們必須同時追求具體部分的完美和匯合的適宜性。 在這部書裏使用“程序設計”一詞時,所關註的是程序的創建,執行和研究。 本書中要討論的各種問題都牽涉到三類需要關註的對象:人的大腦,計算機程序的集合以及計算機本身。 每一個計算機程序都是現實中的或者精神中的某個過程的一個模型,通過人的頭腦孵化出來。這些過程出現在人們的經驗或者思維之中數量上數不勝數,詳情瑣碎繁雜,任何時候人們都只能部分地理解它們。 我們很少能通過自己的程序將這種過程模擬到永遠令人滿意的程度。正因為如此,即使我們寫出的程序是一個集經過仔細雕琢的離散符號,是交織在一起的一組函數,它們也需要不斷的演化:當我們對於模型的認識更深入,更擴大,更廣泛時,就需要去修改程序,直至這一模型最終到達了一種亞穩定狀態。而在這時,程序中就又會出現另一個需要我們去為之奮鬥的模型。 計算機程序設計領域之令人興奮的源泉,就在於它所引起連綿不絕的發現,在我們的頭腦之中,在由程序所表達的計算機制之中,以及在由此所導致的認識爆炸之中。如果說藝術解釋了我們的夢想,那麽計算機就是以程序的名義執行著它們。 就其本身的所有能力而言,計算機是一位一絲不茍的工匠:它的程序必須正確,我們希望說的所有東西,都必須表述的準確到每一點細節。就像在其他所有使用符號的活動中一樣,我們需要通過論證使自己相信程序的真。 大的程序是從小東西成長起來的,開發出一個標準化的程序結構的武器庫,並保證其中每種結構的正確性——我們稱它們為慣用法,再學會如何利用一些已經證明很有價值的組織技術,將這些結構組合成更大的結構,這些都是至關重要的。 本書中將詳盡地討論這些技術。理解這些技術,對於參與這種被稱為程序設計的具有創造性的事業是最最本質的。特別值得提出的是,發現並掌握強有力的組織技術,將提升我們構造大型的重要程序的能力。反過來說,因為寫大程序非常耗時費力,這也推動著我們去發明新方法,減輕由於大程序的功能和細節而引起的沈重負擔。 不要問得過於頻繁,以免忽略了程序設計的樂趣,使自己陷入一種喜憂參半的呆滯狀態中。 在我們寫出的程序裏,有些程序執行了某個精確的數學函數(但是絕不夠精確),例如排序,或者找出一系列數中的最大元,確定素數性,或者找出平方根。我們將這種程序稱為算法,關於它們的最佳行為已經有了許多認識,特別是關於兩個重要的參數:執行的時間和對數據存儲的需求。程序員應該追求好的算法和慣用法。即使某些程序難以精確的描述,程序員也有責任去估計它們的性能,並要繼續設法去改進之。 前言 我們的學生已經變成了我們的創造者。 一臺計算機就像是一把小提琴。你可以想象一個新手試了一個音符並丟掉了它。後來他說,聽起來真難聽。我們已經從大眾和我們的大部分計算機科學間那裏反復聽到這種說法。他們說,計算機程序對個別具體用途而言確實是好東西。但他們太缺乏彈性。一把小提琴或者一臺打字機也同樣缺乏彈性,那時你學會了如何去使用它們之前。 ——Marvin Minsky 一個計算機語言並不僅僅是讓計算機去執行操作的一種方式,更重要的,它是一種表述有關方法學的思想的新穎的形式化媒介。因此,程序必須寫得能夠供人們閱讀,偶爾地去供計算機執行。其次,我們相信,在這一層次的課程裏,最基本的材料並不是特定程序設計語言的語法,不是有效計算某種功能的巧妙算法,也不是算法的數學分析或者計算的本質基礎,而是一些能夠用於控制大型軟件系統的智力復雜性的技術。 我們的目標是,使完成了這一科目的學生能對程序設計風格要素和審美觀有一種很好的感覺。她們應該掌握了控制大型系統中的復雜性的主要技術。她們應該能過去讀50頁長的程序,只要該程序是以一種值得模仿的形式寫出來的。她們應該知道在什麽時候哪些東西不需要去讀,哪些東西不需要去理解。她們應該很有把握地去修改一個程序,同時又能保持原來作者的精神和風格。 這些技能並不僅僅適用於計算機程序設計。我們所教授和提煉出來的這些技術,對於所有工程設計都是通用的。我們在適當的時候隱藏起一些細節,通過創建抽象去控制復雜性。 設計這門課程的基礎是我們的一種信念,“計算機科學”並不是一種科學,而且其重要性也與計算機本身無太大關系。計算機革命是有關我們如何去思考的方式,以及我們如何去表達自己的思考的一個革命。在這個變化裏最基本的東西,就是出現了這樣一種或許最好是稱為過程性認識論的現象——這就是如何從一種命令式的觀點去研究知識的結構,這一觀點是與經典數學領域中所采用的更具說明性的觀點完全不同的。數學為精確處理“是什麽”提供了一種框架,而計算則為精確處理“怎樣做”的概念提供了一種框架。 第一章 構造過程抽象 心智的活動,除了盡力產生各種簡單的認識之外,主要表現在如下三個方面: 1)將若幹簡單認識組合為一個復合認識,由此產生出各種復雜的認識。2)將兩個認識放在一起對照,不管它們如何簡單或者復雜,在這樣做是並不將它們合而為一。由此得到有關它們的相互關系的認識。3)將有關認識與那些在實際中和它們同在的所有其他認識隔離開,這就是抽象,所有具有普遍性的認識都是這樣得到的。 ——John Locks 《有關人類理解的隨筆》 真實的程序設計則需要極度細心,需要經驗和智慧。軟件工程大師們能組織好自己的程序,使自己能合理地確信這些程序所產生的計算過程將能完成預期的工作。他們可以事先看到自己系統的行為方式,知道如何去構造這些程序,使其中出現的意外問題不會導致災難性的後果。而且,在發生了這種問題時,他們也能排除程序中的錯誤。設計良好的計算系統就像設計良好的汽車或者核反應堆一樣,具有某種模塊化的設計,其中的各個部分都可以獨立地構造,替換,排除錯誤。 1.1 程序設計的基本元素 一個強有力的程序設計語言,不僅是一種指揮計算機執行任務的方式,它還應該成為一種框架,使我們能夠在其中組織自己有關計算過程的思想。這樣,當我們描述一個語言時,就需要將註意力特別放在這一語言所提供的,能夠將簡單的認識組合起來形成更復雜認識的方法方面。每一種強有力的語言都為此提供了三種機制:
  1. 基本表達形式,用於表示語言所關心的最簡單的個體
  2. 組合的方法,通過它們可以從較簡單的東西出發構造出復合的元素
  3. 抽象的方法,通過它們可以為復合對象命名,並將它們當作單元去操作
在程序設計中,我們需要處理兩類要素:過程和數據(以後讀者將會發現,它們實際上並不是這樣嚴格分離的)。非形式地說,數據是一種我們希望去操作的“東西”,而過程就是有關操作這些數據的規則的描述。這樣,任何強有力的程序設計語言都必須能表述基本的數據和基本的過程,還需要提供對過程和數據進行組合和抽象的方法。 1.1.1 表達式 前綴表示: 將運算符放在所有運算對象左邊 1.1.2 命名和環境 程序設計語言中一個必不可少的方面,就是它需要提供一種通過名字去使用計算對象的方式。我們將名字標識符稱為變量,它的值也就是它所對應的那個對象。 一般而言,計算得到的對象完全可以具有非常復雜的結構,如果每次需要使用它們時,都必須記住並重復地寫出它們的細節,那將是極端不方便的事情。實際上,構造一個復雜的程序,也就是為了去一步步地創建出越來越復雜的計算性對象。 1.1.3 組合式的求值 解釋器本身就是按照下面過程工作的: 1)求值該組合式的各個子表達式 2)將作為最左子表達式(運算符)的值的那個過程應用於相應的實際參數,所謂實際參數也就是其他子表達式的值 一般而言,我們應該把遞歸看做一種處理層次性結構的(像樹這樣的對象)極強有力的技術。事實上,“值向上穿行”形式的求值形式是一類更一般的計算過程的一個例子,這種計算過程稱為樹形積累。 1.1.4 復合過程 過程定義:這是一種威力更加強大的抽象技術,通過它可以為復合操作提供名字,而後就可以將這樣的操作作為一個單元使用了。

讀書筆記 -- 計算機程序的構造和解釋