函數式語言基本知識
一些作者已經強調了面向對象程序設計和面向數值程序設計的區別。MacLenna(1982)指出,值(例如數字17)是應用式的和只讀的,他們總是抽象的。對象(例如實例)在一定范圍內存在,可以被創造、撤銷、共享和更新。數值是引用透明的,引用它的一切事情將使用同樣的數值。Smalltalk也因此受到一些批評,在Smalltalk中任何事物都是對象。無法實現一種正確的區分將導致幾個危險。不清楚共享的數據結構是否可能被錯誤地更新,或者存在著一個以潛在的代價昂貴的復制開銷。在給出了應用式程序設計或面向數值的程序設計的一切優點以后,為什么我們應該完全需要對象呢?
首先,如果我們所采用的數據結構對應于真實世界的話,那么計算機系統里現實世界模擬將會被大大簡化。文件是對象,他們不能被代數描述。在普通程序設計語言中,變量是對象,他們的標識和區分是通過他們的位置,而無需考慮它們的當前值是什么。一個值屬于一個類型,而一個對象屬于一個類,本質的區別是:具有相同描述的兩個對象可能并不相同,而相同的描述不可能是兩個不同的值。例如,只可能有一個值等于17的整數,但蒙娜麗莎畫像可以有兩個完全一樣的副本。反之則是不正確的,這可以通過下面的情況進行說明。考慮具有不同描述的兩個對象(早晨的星星和晚上的星星),他們代表的是同一物理對象(金星)。許多語言都混淆了這個問題,例如,Pascal中的文件可能無法被賦予表達式或在表達式中使用,盡管他們的聲明是通過和其他類型同樣的方式。模擬系統的程序員必須處理“狀態”和狀態的變化,他們必須處理時間或(至少在人工智能里的)可能世界。應用式程序設計不是為此目的而設計的,而是為了處理不受時間影響的數學抽象。
那么,我們所需要做的就是清楚地區分值和對象以及支持這種區分并允許使用恰當模型(值或對象)的一種語言。
函數是程序設計是一種風格,包括建立在形式邏輯和數學基礎上的語言,例如Lisp或ML。普通程序通過向變量賦值而發生作用,這些變量代表了內存中的存儲位置。任何以前存儲的值將會被重寫并永久消失,除非事先采取了有關步驟。應用式程序語言(比如Lisp)不采用這種破壞的賦值過程。相對于命令式編程,應用式程序設計不允許賦值或側放作用。在實際中,這意味著要節省存儲空間,處理器必須周期性地執行一些無用存儲單元收集以清除那些不再需要的值。另一個普遍的特征是“延遲計算”,通過這種方式,數值在函數用到之前是不被計算的。這種類型的語言建立在函數應用和組合的基礎之上,他們依賴于以以“lambda演算”而聞名的邏輯系統,對lambda演算,我們將在下面進行說明。當應用式程序設計維持“參照透明性”的時候,這就是說每個表達式或變量在給定作用于范圍內具有相同的值,所有變量都是局部的。那么在這種情況下,應用式程序設計也就變成了函數是程序設計。這暗示我們可以用一個相等值來替換一個表達式,而不會改變整個表達式的值。這個屬性在定理證明和數據庫查詢中是很有用的,因為其中重寫和替換是很基本的。雖然這種作用與規則很容易讓人想起面向對象的語言,但函數式程序設計不允許對象具有狀態。一種過程語言命令計算機如何執行一個特定的任務。一種非過程語言僅僅告訴計算機該做些什么,而不是怎么做。思考下列一個數據庫查詢,該查詢詢問每個部門各有多少個雇員以及總薪水和平均薪水是多少。
- SELECT DNAME, JOB, SUM(SAL), COUNT(*), AVG(SAL)
- FORM EMPLOYEE,DEPARTMENT
- WHERE EMPLOYEE.DEPTNO=DEPARTMENT.DEPTNO
- GROUP BY DNAME,JOB
實際上,這個查詢產生正確輸出,但結果是不必與我們相關的。上面所用的語言是SQL語言,注意他并沒有告訴計算機如何回答這個問題。這涉及到獲取雇員表單,按部門和工作進行排序,然后計算人數以及平均薪水和總薪水。最后,在輸出結果中,部門編號必須被部門名稱所代替。這本是一個相當復雜的過程,其中涉及到讀紀錄和保存每一階段的中間結果。但這種建立在關系代數基礎之上的非過程SQL是所有這些都是不必要的。在SQL
的執行過程中,存在著引入了一種過程性元素的內置函數。純粹形性是一個非常珍貴的幫助。
術語“說明性”比“非過程”更通用一些,因為它包括了純說明性語言。這個術語更多的是與數據表示方法有關,而于特定的程序設計風格并無太大關系。說明性語言的對立語言通常稱為命令式語言,但這種用法在更時髦但不太悅耳的“非過程”的攻擊下邊的落伍。Prolog語言也是一種說明性的非過程風格(盡管一種修剪(!)操作的出現使他同樣能夠以一種不靈活的過程風格被使用)。現在,讓我們轉向使得這種語言成為可能的邏輯。
Prolog和SQL都是基于一階謂詞演算(這是數學邏輯的一種形式),SQL是建立在更小自己的基礎之上,因此可表達性較差。這些語言金當他們的可表達性像Prolog一樣時才通常被稱為邏輯程序設計語言。函數式程序設計語言建立在另一種邏輯系統的基礎(lambda演算)之上,通常認為它是邏輯程序設計語言,盡管它們深深根植于邏輯。
函數式程序語言有一些明顯的好處,這些好處包括:
◆它們的形式化基礎。
◆通過增加額外的可重用功能,他們很容易被擴展。
◆統一的程序設計隱喻,從而,每件事都是一個函數。
◆較高級的結構體(函數的函數)容易表達。
◆支持多態性類型(像ML一樣)或完全風格的類型自由(像Lisp一樣)。
【相關閱讀】