一、基礎知識
(一)編程語言(程序設計語言)的分類?
通常可分為4類:命令式語言、函數式語言、邏輯語言和面向對象的語言(實際上還有很多不同的划分版本)
1、命令式編程語言(imperative language)
計算機體系結構是影響語言設計的一個重要因素,目前的大多數語言都是圍繞着馮諾依曼結構設計的,
這些語言稱為“命令式語言”。
命令式語言的核心特征:
(1)變量(馮諾依曼結構的存儲單元)
(2)賦值語句(數據傳輸)
(3)迭代形式的循環(馮諾依曼結構中實現循環的最高效形式)
2、函數式編程語言(functional language)
命令式編程語言是以馮諾依曼這種體系結構為模型,而函數式程序語言的目的是盡可能的模擬數學函數。
函數式語言的核心特征:
(1)以“函數”為首,如同命令式語言中的“變量”,函數可以賦值給其他變量,可以作為其他函數的參數,
或者作為其他函數的返回值。
(2)不修改變量的值
(3)只有表達式,沒有語句。此處的語句指的是沒有返回值得某些操作。
(4)引用透明(Referential transparency),函數的運行不依賴與外部變量或“狀態”,簡單的說就是,
同一個輸入(參數),總是會產生同一個輸出(返回值),這與數學函數的特征很一致。
命令式語言因為全局變量等的存在,就無法做到這一點。
(5)對比命令式語言,遞歸形式的循環
3、邏輯程序設計語言(logic programming language)(未研究)
邏輯程序設計語言:基於邏輯符號邏輯的語言稱為邏輯程序設計語言,或者聲明性語言
邏輯程序設計:用一種符號邏輯作為程序設計語言來進行程序設計,通常稱為邏輯程序設計
邏輯式編程語言是基於規則的編程語言
程序是事實和規則集,通過符號邏輯表示程序,並使用邏輯推導過程來生成結果。
4、面向對象語言(object oriented language)
聽起來最親切的一個種類..........
嚴格來說,面向對象語言不應該處在與命令式語言並列的狀態,面向對象語言的設計也是依據馮諾依曼結構,
它是從命令式語言發展而來,我覺得它本身就是命令式語言。
“面向對象”:強調的是開發模式,與它相對的開發模式就是“面向過程”
所以說就是“命令式語言”通常指的是“面向過程開發的編程語言”,比如C語言;
“面向對象語言”指的就是“面向對象開發的編程語言”,比如C++和Java。
主要特征:
(1)封裝:將數據和方法封裝成類
(2)繼承:子類繼承父類,可以自動共享父類的數據結構和方法
(3)多態:子類可以修改父類的方法
5、其他語言:
(1)腳本語言(Scripting language)(python、JavaScript等等)
腳本語言也是一類語言,只不過分類的依據與上述不同,腳本語言屬於“命令式語言”的范疇
單拎出這個分類是由於其的運行方式——解釋執行,沒有編譯過程
(2)可視化語言
同樣是命令式語言的一個子類,能夠以拖放的方式生成代碼段(比如.NET)
(3)標記語言(markup language)(HTML、XML等)
這種語言,不算做編程語言;
但是某些標記語言(比如HTML和XML)的擴展中,也加入了一些程序設計的功能
——標記與程序設計混合語言(比如JSP標准標簽庫中的JSTL)
(4)還有一些特殊用途的語言等等
(二)語言執行方式?
1、編譯執行——針對編譯語言
簡單理解,編譯執行就是先將源語言(通常是高級語言)翻譯成目標語言機器語言(01碼),之后再執行。
源語言——>目標語言的翻譯過程,包括詞法分析、語法分析、語義分析多個步驟
什么是翻譯,用會話語言想一下就懂了,翻譯就是從一種語言換成另一種語言的過程(中文—>英文)
(我之所以在這寫這么多,是因為這個簡單的道理我是經過很久才悟的....)
2、完全解釋執行——針對動態語言(腳本語言)
對比編譯執行,就是沒有翻譯的過程,程序由另一個稱為解釋器的程序(虛擬機)解釋執行。
3、混合執行——編譯與完全解釋的折中
源語言——(翻譯)——> 中間語言——(解釋執行)——>結果
引入中間語言的目的是什么呢?就是這種語言更便於解釋執行
比如Java:
(1)首先,將源代碼翻譯成中間語言(中間形式)——字節碼
(2)Java虛擬機(字節碼解釋器)對字節碼進行解釋執行
由此也可以理解,編譯有兩種可能性:
(1)對於編譯語言來說:編譯是將源代碼編譯成能夠作用於真機的指令,生成的語言是直接作用於硬件的
(2)對於動態語言來說:編譯是將源代碼編譯成一個中間形式,比如字節碼
字節碼不是作用於硬件,而是虛擬機
字節碼是什么?——就是一系列的字節,每個字節表示一個指令
(三)開發環境
開發環境不難理解,是軟件開發中使用的工具集
這個工具集可以只包含一個文件系統、一個文本編輯器、一個鏈接器和一個編譯器,
也可以包含很多集成的工具,每個工具都可以通過統一的用戶界面來使用。
二、函數式編程
所以什么是函數式編程呢..........................,首先再復習一下基礎知識.....................................
(一)數學函數
數學函數是從一個集合到另一個集合的映射,前者稱為定義域,或者稱為值域。
映射過程的描述:表達式或者表
特征:
(1)映射表達式的求值順序由遞歸表達式和條件表達式控制
(2)給定同一個參數,總是輸出值域幾個中的同一個元素
1、簡單函數——函數名后跟括號內的一組參數,之后是表達式,例如:
f(x)=x*x*x,其中x是實數
此函數:
(1)定義域和值域都是實數
(2)如果執行求f(2),即參數是2,在整個求值過程中,x的值恆為2,不改變
2、λ標記法——提供了一種定義匿名函數的方法。
λ表達式:是一個匿名函數,說明了函數的參數和映射,然而此函數沒有名字,
λ表達式和其他函數定義一樣,可以有一個以上的參數——λ(x)x*x*x
λ計算:一個使用λ表達式的計算模型
λ計算是函數式編程語言的靈感所在
3、高階函數——以一個或多個函數作為參數,兩種類型
(1)函數組合,有兩個函數參數,並生成一個函數
該函數的值是將第一個實參函數應用到第二個實參函數的結果上。
h(x)=f(g(x)); f(x)=x+2; g(x)=3*x;
(2)以單個函數為參數,可以應用到一組自變量上,結果組合成列表或者序列
h(x)=x*x;
a(h,(2,3,4))——>(4,9,16)
(二)函數式程序設計基礎
最根本的一點:函數式程序設計語言的目的是盡可能的模擬數學函數!
命令式語言:計算表達式,將結果存儲在存儲單元中(程序中的變量),這就是賦值語句的作用
純函數式程序設計語言:
(1)沒有變量,沒有賦值語言;
(2)沒有變量,也因此沒有迭代結果(因為迭代是由變量控制的),重復執行必須用遞歸
(3)程序:就是函數定義和函數應用的說明
(4)程序的執行:對函數應用的求值
(5)給定相同的參數,執行函數總是生成相同的結果,這一特性稱為引用透明
這一特性使得語義比命令式語言更簡單,更易測試
(6)提供了一組函數,一組函數組成更復雜的函數
ps. 上述均是針對純函數式語言,但是目前大多數函數語言都包含一些命令式語言的特性,比如變量和賦值語句;
早期的函數式語言通常是用解釋器來執行,但現在大多數都是編譯執行。
(三)命令式語言對函數式編程的支持(以python為例)
1、lambda表達式——定義匿名函數
lambda a,b : 2*a+b
2、支持高階函數
(1)函數作為參數傳遞
1 >>> def f(x): 2 return x*x 3 4 >>> add(-5,9,f) 5 106 6 >>> def f(x): 7 return x*x 8 9 >>> def add(x,y,f): 10 print f(x)+f(y) 11 12 13 >>> add(2,3,f) 14 13
(2)內置的高階函數map()
map函數有兩個參數,一為函數,一為列表,返回值對每一個參數求值
1 >>> map(lambda x:x**3,[1,2,3,4,5]) 2 [1, 8, 27, 64, 125] 3 >>> def f(x): 4 return x*x*x 5 6 >>> map(f,[1,2,3,4,5]) 7 [1, 8, 27, 64, 125] 8 >>>
(3)內置高階函數reduce()
map函數有兩個參數,一為函數,一為列表,返回值對每一個參數反復調用函數

(4)內置高階函數filter()——判斷

(5)..........
3、支持閉包....
(四)函數式編程的優點
1、適用於並行編程——因為不會修改變量,所以過程中不需要同步互斥;
2、惰性求值:這個需要編譯器的支持。表達式不在它被綁定到變量之后就立即求值,而是在該值被取用的時候求值;
3、函數確定性:給定同一個參數,肯定是有一個同樣的輸出
4、代碼更簡潔
..........
其他:
1、命令式語言是依據馮諾依曼結構的,但是函數式語言並沒有
所以說在當前的體系結構上,函數式語言的優勢體現的並不明顯,還是難以取代命令式語言
2、純函數式語言現在很少,大多引入了命令式語言的特性
3、函數式語言近來被關注的越來越多,也正是因為命令式語言加入了對其的支持
4、理解函數式語言,最重要的就是理解它的設計盡可能的依照了數學函數的思想