本書簡介
《計算機程序的構造與解釋》這本書是MIT計算機科學學科的入門課程,
大部分學生在學這門課程前都沒有接觸過程序設計,也就是說這本書是針對編程新手寫的。
雖然是入門課程,但起點比較高,看懂里面的知識需要比較扎實的數學功底,
最起碼要有高中數學水平,如果高中數學沒學好,看起來會比較吃力。
當然,這本書的目標不是教你去做數學分析,或者讓你學會使用LISP,他的目標我理解如下
- 學會使用編程的一些基本元素,以編程的方式思考問題
- 學會如何使用抽象和創造抽象來解決復雜問題
- 學會如何良好的組織代碼來編寫大型軟件系統,控制其中的復雜性
- 是識別出好的程序設計和差的程序設計
以數學來示范各種編程原理是因為數學問題比較普遍,好多概念大家都有所接觸,
沒有二義性,不需要把時間花在問題描述和需求分析上。以LISP來進行編程原理解
說是因為LISP語法非常簡單,不需要把時間花在講解語法上。
程序設計的基本要素
表達式
LISP可能不好安裝,我們就用Javascript來練習第一章的示范吧,打開Chrome瀏覽器,
按F12打開開發人員工具,在Console標簽里就可以寫代碼了。
如果你還不知道編程能干什么,Javascript是啥東西,沒關系,
我們可以先來實現一些簡單的數學計算,在Chrome的Console里輸入如下代碼
>128
128
>128 + 12
140
>128 / 16
8
>128 - 28
100
>50 * 2
100
>3 + 2 * 10
23
>2 * 10 * 3.14
62.800000000000004
上面代碼的大于號不用輸,表示輸入提示符,可以看到輸入一些數學式子后Console會自動打印出
這個式子的求值結果。暫時先不用管背后的原理是什么,你現在已經開始在編程了。
上面你輸入的式子就叫做表達式,里面的數就是普通的數字,+,-,*,/這些叫操作符,
操作符可以操作數,他操作的是自己兩邊的數。
命名和環境
像上面的例子里2 * 10 * 3.14
其實就是在計算一個半徑為10的圓的周長,3.14就是圓周率π,
計算圓的周長的公式不是2πr嗎?
如果我們要計算好多圓的周長,那么每次都要把3.14打出來嗎?能不能給3.14起個名字呢?
能,肯定能。能給某些計算對象命名是所有編程語言里最重要的一個功能,如下。
>var pi = 3.14
undefined
>2 * pi * 10
62.800000000000004
>2 * pi * 5
31.400000000000002
>2 * pi * 8
50.24
上面的第一句var pi = 3.14
就相當于給3.14起了個名字pi,后面計算周長的表達式都可以用pi來代替3.14。
這就是一個最簡單的抽象手段,你不需要記住pi的值具體是多少,只需要記住pi就表示圓周率就行了。
這個思路很關鍵,以后寫代碼寫多了,你會發現你寫的代碼越來越復雜,能夠給你寫的部分代碼進行命名,
然后使用的時候不用關心復雜的細節,就可以控制住這種復雜性,寫出復雜的大程序來。
組合式的求值
像3 + 2 * 10
這個式子,*會先把2和10進行乘法計算,得到20,然后+會把3和20進行相加,
得到23,整個過程和數學里的加減乘除運算規律是一樣的。如果你想執行(3 + 2) * 10
的結果,
也可以直接把這個式子在Console里輸入,也能正確的執行。
你在寫2 * pi * 10
時,pi會自動替換成3.14,這說明Javascript解釋器幫你存儲了pi到3.14
的對應,這種存儲我們叫環境
,每個環境里都存儲了一些名字和計算對象的對應關系。
環境
是個普遍的概念,它為求值的過程提供了一種上下文,對于我們理解程序
的執行起著很重要的作用。
比如你要執行(3 + 2 + 5) * (2 * (1 + 2))
,這個表達式的求值過程就稍微復雜點了。
總體來看呢,這個式子分成兩個部分,一個是(3 + 2 + 5)
,一個是(2 * (1 + 2)),然后
這兩個部分進行想乘。要想得到這兩個部分的相乘呢,又要先得到這兩個部分的結果,怎么得到呢?
我們發現這兩個部分其實也是表達式,比如(2 * (1 + 2))
,其實也有兩部分組成,一個
是2
,一個是(1 + 2)
,這兩個部分相乘。這樣從外到里分析,肯定會分析出最簡單的不
能再分的表達式,可以直接求出結果。
這個過程就叫做遞歸
,先不用計較復雜的解釋,就先理解復雜表達式的求值需要先對子表
達式進行求值,子表達式的求值需要對子表達式的子表達式求值,這個過程就叫遞歸
。
遞歸是個剛開始不太好理解的概念,但掌握后用它來理解很多問題就很輕松了,以后會經常
遇到,加深印象。需要提的就是遞歸要有幾個注意的地方。
- 遞歸分成好多個步驟
- 每個步驟要把整個事情向前推進,每次推進都向最終點更近一步。
- 整個遞歸過程要有個最終點,否則整個過程就無法終止了。
比如復雜表達式的求值過程就分成多個步驟,每個步驟就是把復雜表達式拆成多個子表達式
,然后每次拆呢,肯定是拆的越來越小,把整個過程向終點推進一步,然后呢如果拆的不能
再拆了,比如1 + 2
直接就能得到結果了,這就到最重點了。
以上說的這些規則,就叫做編程的語法,慢慢你會發現有的編程語言的語法特別多,需要記住的東西特別多,比如各種括號,特殊字符,關鍵字。
而有的編程語言的語法特別少,基本上不用記,一大屏代碼看到的都差不多的格式。剛學編程的時候建議選擇后面一種的編程語言,如Javascript, Python,盡量學習一些編程的本質,而不是各種語法。
文章列表