這篇博文裡說到程式=資料+過程,資料分為不同型別,每種型別有不同的操作過程。例如,兩個指標變數相加是無意義的,所以對指標型別來說加法操作是「不允許」的。在彙編層,每乙個資料,每一步資料操作過程都是原子級的,更高層次的資料和操作概念需要「高階」語言的支援,也就是這個語言配套的編譯器/直譯器能將這個「新」型別資料、「新」過程解釋/編譯成底層概念,才能實際執行。這裡的兩個「新」字就體現了程式的抽象機制。程式抽象可以「粗暴」的分為兩類:過程抽象和資料抽象。之所以說粗暴是因為資料和過程的界限有時是模糊難以清晰劃分的。
計算機裡的過程是對真實世界過程的抽象,在現實中需要處理事務、需要繪畫、需要傳遞資訊、需要運算……。
這些在計算機上都可以完成,對應的有計算機輔助設計、email、im、大型運算中心等等。這些過程的操作物件就是真實世界的資料抽象。這些資料或多或少、或顯著或隱晦的表示著真實世界的某種狀態。資料抽象和過程抽象共同模擬了真實的世界,在現代社會的各行各業,計算機技術都在發揮著作用,助推人們更好更便捷的處理任務。而程式語言就是描述「如何做」的工具,工具反過來也會影響「如何描述」和「如何做」。不同語言有各自的特點,但目標是一樣。就像自然語言一樣,發音、字形、語法不同,但都是人類溝通的工具。語言反過來也會影響人的思維。計算機語言也有同樣的效果,它影響程式設計師的程式設計思想,所以程式語言也在不斷進化中。
任何語言都必須包含三種機制:
所有的表示式都有值,程式的執行過程即是表示式的求值過程。資料表示式的值就是資料的表示方式,簡單數值表示式如25,它的值就用整數25表示,復合表示式如結構體struct,它的值就是這個結構體內的資料表示形式;過程表示式的值就是對資料的「操作」,也就是過程體,如「+」加法表示式,它的值就是將它左右(或者其他,不同語言的表示方式不同)的其他表示式的值做相加操作。
/**
**scheme語言舉例
*自定義了乙個加法過程,它接收兩個引數,相加並將結果返回
*下面是求值組合表示式,它的左邊運算子就是剛才定義的過程
*引數1為另乙個復合過程( + 1 2 ),引數2為最簡單數值表示式
*/( define mysum
( lambda ( a b ) ( + a b ) ) )
( mysum ( + 1 2 ) 3 )
這段程式就包含了上面描述的三個機制,define代表了一種抽象的方法,它表示自定義了乙個過程,它類似於重寫了加法,但這裡mysum只允許兩個引數;1、2、3和「+」是基本的表示式;而(+ 1 2)是組合的方法,將基本的表示式組合起來,它的值就是將「+」加法運算子運用於運算元1、2上得出的結果。
上面描述了第一層次的過程抽象:將為實現目的的若干操作封裝成乙個過程,使得過程的使用者不需要了解該過程內部實現細節,而只要了解過程的介面,傳入適當的引數,就能得到預期的結果。這裡的define規則給該過程命名,mysum就如同「+」、「-」、「*」、「/」等內部過程一樣,可以看作自定義的運算子,在表中的最左位置,它的值就是作用於其他資料物件的結果。
下面考慮另乙個層次的抽象問題,定義以過程作為引數或者返回值的過程。對比下面的**:
/*
*求和公式
*/( define square
( lambda ( x ) ( * x x ) ) )
( define cube
( lambda ( x ) ( * x x x ) ) )
( define sum-square
( lambda ( a b )
( if (> a b)
0( + (square a) ( sum-square ( + a 1 ) b ) ) ) ) )
( define sum-cube
( lambda ( a b )
( if (> a b)
0( + (cube a) ( sum-square ( + a 1 ) b ) ) ) ) )
上面的**定義了四個過程,其中square(x)、cube(x)分別計算x的平方和立方,sum-square(a b)、和sum-cube(a b)計算從a到b的平方和與立方和。仔細看會發現求和的過程中的模式很相似。求平方和的過程中,先比較a是否大於b,如果大於b則返回0,否則求a的平方,然後遞迴呼叫sum過程,並將這兩個結果相加,遞迴的過程中引數a加1。求立方和的過程就是在求a的立方時不同,其他部分很相似。這裡面是否隱藏了某種模式,可以綜合處理上述兩個過程?
( define ( lambda ( a b )
( if ( > a b )
0( + ( a )
( ( 上面的**就是計算平方和與立方和的公共模式,term、name和next是需要填入的過程,以滿足新的求和公式。這就是第二次的過程抽象,以過程作為過程的引數,使得語言程式設計的威力大增。
在《電腦程式的構造和解釋》第一章求方程的不動點例子中,將過程的抽象再提高乙個層次。所謂不動點就是滿足x=f(x)方程的x值。求解的方法就是首先猜測乙個值x,然後計算f(x)、f(f(x))、f(f(f(x)))...,直到值的變化不大,就找到它的不動點了。看**:
( define tolerance 0.00001)
( define ( fixed-point f first-guess)
( define ( close-enough? v1 v1 )
( < (abx ( - v1 v2 )) tolerance))
( define ( try guess )
( let (( next ( f guess )))
( if ( close-enough? guess next)
next
( try next ))))
( try first-guess))
上面的**在fixed-point過程內部定義幾個輔助過程,首先是close-enough?會比較v1和v2是否足夠接近;然後在try過程中,給next賦值為f(guess)的值,然後比較guess和next是否接近,如果是則返回next,否則繼續求f(next)的值,直到close enough。 《電腦程式的構造和解釋》學習筆記 數值積分
一 數值分析 數值分析 英語 numerical analysis 是指在數學分析 區別於離散數學 問題中,對使用數值近似 相對於一般化的符號運算 演演算法的研究。參考 數值分析 研究領域 1.函式求值 2.內插法 外推法 曲線擬合及回歸 3.求解方程及方程組 4.求解特徵值或奇異值問題 5.最優化...
電腦程式的構造和解釋 SICP
又名 structure and interpretation of computer programs,second edition 譯者 裘宗燕 isbn 9787111135104 頁數 473 定價 45.0 出版社 機械工業出版社 裝幀 平裝 出版年 2004 2 1 本書1984年出版,...
電腦程式的構造和解釋 練習題1 44
平滑函式的公式為 f s x f x dx f x f x dx 3f s x f x dx f x f x dx 3 fs x f x dx f x f x d x 3他的幾何意義應該是將每個點的導數,變化率變小。說簡單點就是函式那塊曲線彎度比較大,加上這個函式就會減小他的彎度,直到他無限接近於一...