再談程式設計正規化—程式語言背後的思想
程式設計正規化
托馬斯.庫爾提出“科學的革命”的正規化論後,Robert Floyd在1979年圖靈獎的頒獎演說中使用了程式設計正規化一詞。程式設計正規化一般包括三個方面,以OOP為例:
1,學科的邏輯體系——規則正規化:如 類/物件、繼承、動態繫結、方法改寫、物件替換等等機制。
2,心理認知因素——心理正規化:按照面向物件程式設計之父Alan Kay的觀點,“計算就是模擬”。OO正規化極其重視隱喻(metaphor)的價值,通過擬人化,按照自然的方式模擬自然。
3,自然觀/世界觀——觀念正規化:強調程式的組織技術,視程式為鬆散耦合的物件/類的組合,以繼承機制將類組織成一個層次結構,把程式執行視為相互服務的物件之間的對話。
簡單來說,程式設計正規化是程式設計師看待程式應該具有的觀點,代表了程式設計者認為程式應該如何被構建和執行的看法。
常見的程式設計正規化有:命令式、過程式、說明式、面向物件、函式式、泛型程式設計等。
Imperative—命令式||過程式
馮諾依曼 機器語言、組合語言 BASIC COBOL C Ada FORTRAN Fortran ,
指令碼式 Perl Python PHP,把用其他語言開發的獨立程式作為部件“粘到一起”
面向物件 Smalltalk C++ Java,將計算建立在獨立的物件的相互作用至上。每個物件有其自身的內部狀態,以及管理自身狀態的可執行子程式
Declarative—說明式||宣告式
函式式 Lisp ML Haskell ,程式被看作是一種從輸入到輸出的函式
資料流 ld Val,語言將計算看成在一些基本的功能結點之間流動的資訊流。結點由輸入單詞的到達觸發,能夠併發操作
邏輯式 Prolog,設法根據一集邏輯規則找出滿足某些特定關係的值
基於模板的 XSLT xml html,
需要提醒的是:程式設計正規化是程式語言的一種分類方式,它並不針對某種程式語言。就程式語言而言,一種語言可以適用多種程式設計正規化。
一些程式語言是專門為某種特定正規化設計的,例如C語言是程序式程式設計語言;Smalltalk和Java是較純粹的面向物件程式語言;Haskell是純粹的函數語言程式設計語言。另外一些程式語言和程式設計正規化的關係並不一一對應,如Python,Scala,Groovy都支援面向物件和一定程度上的函數語言程式設計。C++是多正規化程式語言成功的典範。C++支援和C語言一樣的程序式程式設計正規化,同時也支援面向物件程式設計正規化,STL(Standard Template Library)使C++具有了泛型程式設計能力。支援多種正規化可能是C++直到現在仍然具有強大的生命力的原因之一。
Swift是一門典型的多正規化程式語言,即支援面向物件程式設計正規化,也支援函數語言程式設計正規化,同時還支援泛型程式設計。Swift支援多種程式設計正規化是由其創造目標決定的。Swift創造的初衷就是提供一門實用的工業語言。不同於Haskell這類出自大學和研究機構的學術性質的程式語言。蘋果推出Swift時就帶著著明確的商業目的:Mac OS和iOS系統的主要程式語言Objective-C已顯老態,Swift將使得蘋果系統的開發者擁有一門更現代的程式語言,從而促進蘋果整個生態圈的良性發展。
指令式程式設計:
指令式程式設計的主要思想是關注計算機執行的步驟,即一步一步告訴計算機先做什麼再做什麼。
從本質上講,它是“馮.諾依曼機”執行機制的抽象,它的程式設計思想方式源於計算機指令的順序排列。
(也就是說:過程化語言模擬的是計算機機器的系統構造,而並不是基於語言的使用者的個人能力和傾向。這一點我們應該都很清楚,比如我們最早曾經使用過的微控制器的組合語言。)
不管你用的是 C, C++ 還是 C#, Java, Javascript, BASIC, Python, Ruby 等等,你都可以以這個方式寫。
程式流程圖是命令式語言進行程式編寫的有效輔助手段。
命令式語言特別適合解決線性(或者說按部就班)的演算法問題。它強調“自上而下(自頂向下)”“精益求精”的設計方式。這種方式非常類似我們的工作和生活方式,因為我們的日常活動都是按部就班的順序進行的。
命令式語言趨向於開發執行較快且對系統資源利用率較高的程式。命令式語言非常的靈活並強大,同時有許多經典應用範例,這使得程式設計師可以用它來解決多種問題。
命令式語言的不足之處就是它不適合某些種類問題的解決,例如那些非結構化的具有複雜演算法的問題。問題出現在,命令式語言必須對一個演算法加以詳盡的說明,並且其中還要包括執行這些指令或語句的順序。實際上,給那些非結構化的具有複雜演算法的問題給出詳盡的演算法是極其困難的。
廣泛引起爭議和討論的地方是:無條件分支,或goto語句,它是大多數程序式程式設計語言的組成部分,反對者聲稱:goto語句可能被無限地濫用;它給程式設計提供了製造混 亂的機會。目前達成的共識是將它保留在大多數語言中,對於它所具有的危險性,應該通過程式設計的規定將其最小化。
命令式對實際事物處理一般可以拆分為以下兩種模式:
-
流程驅動:類似 一般就是主動輪詢 在幹活中還要分心 主動去找活幹 這樣有空餘的時間也完全浪費掉了
採用警覺式者主動去輪詢 ( polling),行為取決於自身的觀察判斷,是流程驅動的,符合常規的流程驅動式程式設計 ( Flow-Driven Programming)的模式。
-
事件驅動:類似 比如公司有一個oa系統 你幹完活的時候只需要看下oa系統有沒分配給你活 沒有可以幹自己的事 不用擔心還有其他事沒幹完
採用託付式者被動等通知 (notification),行為取決於外來的突發事件,是事件驅動 的,符合事件驅動式程式設計 ( Event-Driven Programming,簡稱 EDP)的模式。
事件驅動程式設計
其實,基於事件驅動的程式設計在圖形使用者介面(GUI)出現很久前就已經被應用於程式設計中,可是隻有當圖形使用者介面廣泛流行時,它才逐漸形演變為一種廣泛使用的程式設計模式。
在過程式的程式設計中,程式碼本身就給出了程式執行的順序,儘管執行順序可能會受到程式輸入資料的影響。
在事件驅動的程式設計中,程式中的許多部分可能在完全不可預料的時刻被執行。往往這些程式的執行是由使用者與正在執行的程式的互動激發所致。
-
事件:就是通知某個特定的事情已經發生(事件發生具有隨機性)。
-
事件與輪詢:輪詢的行為是不斷地觀察和判斷,是一種無休止的行為方式。而事件是靜靜地等待事情的發生。事實上,在Windows出現之前,採用滑鼠輸入字元模式的PC應用程式必須進行序列輪詢,並以這種方式來查詢和響應不同的使用者操做。
-
事件處理器:是對事件做出響應時所執行的一段程式程式碼。事件處理器使得程式能夠對於使用者的行為做出反映。
事件驅動常常用於使用者與程式的互動,通過圖形使用者介面(滑鼠、鍵盤、觸控板)進行互動式的互動。當然,也可以用於異常的處理和響應使用者自定義的事件等等。
事件的異常處理比使用者互動更復雜。
事件驅動不僅僅侷限在GUI程式設計應用。但是實現事件驅動我們還需要考慮更多的實際問題,如:事件定義、事件觸發、事件轉化、事件合併、事件排隊、事件分派、事件處理、事件連帶等等。
其實,到目前為止,我們還沒有找到有關純事件驅動程式設計的語言和類似的開發環境。所有關於事件驅動的資料都是基於GUI事件的。
屬於事件驅動的程式語言有:VB、C#、Java(Java Swing的GUI)等。它們所涉及的事件絕大多數都是GUI事件。
此種程化正規化要求程式設計師用按部就班的演算法看待每個問題。很顯然,並不是每個問題都適合這種過程化的思維方式。這也就導致了其它程式設計正規化出現,包括我們現在介紹的面向物件的程式設計正規化。
從程式設計的發展史來談面向物件的出現。當軟體還非常簡單的時候,我們只需要面向過程程式設計:
定義函式
函式一 函式二 函式三 函式四
定義資料
資料一 資料二 資料三 資料四
最後各種函式,資料的操作。
當軟體發展起來後,我們的軟體變得越來越大,程式碼量越來越多,複雜度遠超Hello World的時候,我們的編寫就有麻煩了:函式和資料會定義得非常多,面臨兩個問題。首先是命名衝突,英文單詞也就那麼幾個,可能寫著寫著取名時就沒合適的短詞用了,為了避免衝突,只能把函式名取得越來越長。然後是程式碼重複,我們可以用函式裡面呼叫函式的方法,但是函式調函式(比如一個功能多個方法(函式),幾個功能混用方法)不便於維護。
面向物件程式
面向物件程式設計(Object-oriented programming OOP)是種通過類、方法、物件和訊息傳遞,來支援面向物件的程式設計正規化。物件則指的是類的例項。它將物件作為程式的基本單元,將程式和資料封裝其中,以提高軟體的重用性、靈活性和擴充套件性,物件裡的程式可以訪問及經常修改物件相關連的資料。在面向物件程式程式設計裡,程式會被設計成彼此相關的物件。
面向物件程式設計可以看作一種在程式中包含各種獨立而又互相呼叫的物件的思想,這與傳統的思想剛好相反:傳統的程式設計主張將程式看作一系列函式的集合,或者直接就是一系列對計算機下達的指令。面向物件程式設計中的每一個物件都應該能夠接受資料、處理資料並將資料傳達給其它物件,因此它們都可以被看作一個小型的“機器”,即物件。即把事情交給最適合的物件去做。
面向物件和麵向過程的區別最直觀的比喻就如:搖(狗尾巴)和 狗.搖尾巴()的區別。
面向物件程式設計的三個基本概念:
-
封裝,面向物件程式設計隱藏了某一方法的具體執行步驟,取而代之的是通過訊息傳遞機制傳送訊息給它。經過深入的思考,做出良好的抽象,給出“完整且最小”的介面,並使得內部細節可以對外隱藏
-
繼承,在某種情況下,一個類會有“子類”。子類比原本的類(稱為父類)要更加具體化;
-
多型,指由繼承而產生的相關的不同的類,其物件對同一訊息會做出不同的響應;
使用面向物件程式語言,易於構建軟體模型。因為,物件很類似乎很容易和現實世界上的所有事物和概念。
面向物件通過介面
-
類,類是相似物件的集合。物以類聚——就是說明。每個物件都是其類中的一個實體。類中的物件可以接受相同的訊息。換句話說:類包含和描述了“具有共同特性(資料元素)和共同行為(功能)”的一組物件。
-
介面,每個物件都有介面。介面不是類,而是對符合介面需求的類所作的一套規範。介面說明類應該做什麼但不指定如何作的方法。一個類可以有一個或多個介面。
-
方法,方法決定了某個物件究竟能夠接受什麼樣的訊息。面向物件的設計有時也會簡單地歸納為“將訊息傳送給物件”。
面向物件技術一方面借鑑了哲學、心理學、生物學的思考方式,另一方面,它是建立在其他程式設計技術之上的,是以前的程式設計思想的自然產物。
如果說結構化軟體設計是將函數語言程式設計技術應用到命令式語言中進行程式設計,面向物件程式設計不過是將函式式模型應用到命令式程式中的另一途徑,此時,模組進步為物件,過程龜縮到class的成員方法中。OOP的很多技術——抽象資料型別、資訊隱藏、介面與實現分離、物件生成功能、訊息傳遞機制等等,很多東西就是結構化軟體設計所擁有的、或者在其他程式語言中單獨出現。但只有在面嚮物件語言中,他們才共同出現,以一種獨特的合作方式互相協作、互相補充。
從上面可以看到,如果按照面向過程的方法去設計汽車,汽車廠商需要採購一大堆零件,然後研究如何除錯、呼叫這一大堆零件以完成一個功能。但是如果採用面向物件的方法去設計汽車,那麼汽車廠商可以採用外包的方式交給專業的制動系統廠商來設計,只需要約定需要開放哪些public方法,輸入什麼輸出什麼就可以了。
靜態函式包物件
將功能有聯絡的一批函式放在一起封裝成一個類。這種類可以完全沒有內部資料,也可以有資料。當有資料時,這些資料充當的其實就是配置(配置對於一個設計優秀的物件,是透明的,物件本身內部的函式根本不知道有配置這個東西,它只知道它需要的每一個數據在它new之後就已經存在this裡了,隨取隨用。配置的給予或獲取方式,是構建物件(new)時才需要去考慮的)這種物件的特點是,它的每一個函式(或方法)對這些資料都是隻讀的,所以不管方法有無被呼叫,被誰呼叫,被呼叫多少次,它也不會改變它的狀態。
領域模型物件
這個概念是相對於傳統的面向資料庫的系統分析和設計而言的。資料庫雖然只用了外來鍵就描述了複雜的大千世界,但軟體開發的難點在於適應變化,並且能夠安全地修改。關係模型看似簡單,但它卻像一張蜘蛛網一樣將所有table和欄位包在一塊,牽一髮而動全身,讓你在修改時如履薄冰,一不小心就會顧此失彼,bug此起彼伏。而OO的封裝特性則剛好可以用來解決這個問題。將業務資料整理成一個個獨立的物件,讓它們的資料只能被自己訪問。留給外界的基本上只是一些介面(方法),資料除非萬不得已,一個都不會公開。外界只能向它傳送訊息,它自己則通過修改自身資料來響應這種訊息。這種物件與第一種物件剛好相反,它一定有資料,而且它的每一個函式存在的目的就是修改自己的資料。且每一次修改都是粗粒度的,每一次修改後,物件也還是處在valid狀態。推薦閱讀《領域模型淺析》,《領域模型,你真的理解的了嗎?》
順便拓展下:領域驅動設計(Domain-Driven Design)-貧血模型-領域模型-充血模型
臨時物件
其它用來解決過程式開發時,超多的變數,超複雜的流程而整理出來的小物件,。這些物件一起協作,最後完成一個傳統成千上萬行的過程式程式碼才能完成的功能。例如現在要連線sql server執行查詢語句並取得結果返回。不使用任何類庫和工具,所有步驟都自己進行,例如解析協議,socket網路連線,資料包收發等。這時候從頭到尾用一個個函式來完成,絕對沒有先劃分出一個個職責分明的物件,讓各物件協作完成這件事情來得更簡單。
但程式設計實踐表明,並不是任何東西成為物件都是一件好事情。舉一個Java中的蹩足的例子:Java中只有物件才能作為引數傳入函式(當然還有原始型別primitive type)。所以為了將函式傳遞給另外一個函式,你需要將函式包裹在一個物件中,通常會用一個匿名類,因為這個類不會有其他作用,只是為了讓Java的一切皆為物件的設計高興。
Java擁有純粹的面向物件概念。它從設計之初,就希望以一切皆為物件的純物件模型來為世界建模。但發展到現在,Java中加入了越來越多非物件的東西。引入了閉包,從而獲得了函數語言程式設計中的一級函式;引入泛型,從而獲得了引數化的型別。這可能暗示了,這個世界是如此得豐富多彩,使用單一模式為世界建模並不會成功。
宣告式程式設計:
宣告式程式設計是以資料結構的形式來表達程式執行的邏輯。它的主要思想是告訴計算機應該做什麼,但不指定具體要怎麼做。
SQL 語句就是最明顯的一種宣告式程式設計的例子,例如:
SELECT * FROM collection WHERE num > 5
除了 SQL,網頁程式設計中用到的 HTML 和 CSS 也都屬於宣告式程式設計。
通過觀察宣告式程式設計的程式碼我們可以發現它有一個特點是它不需要建立變數用來儲存資料。
另一個特點是它不包含迴圈控制的程式碼如 for, while。
函數語言程式設計和宣告式程式設計是有所關聯的,因為他們思想是一致的:即只關注做什麼而不是怎麼做。但函數語言程式設計不僅僅侷限於宣告式程式設計。
函數語言程式設計
函數語言程式設計(functional programming)或稱函式程式設計、泛函程式設計,是一種程式設計正規化,它將計算機運算視為函式運算,並且避免使用程式狀態以及易變物件。其中,λ演算(lambda calculus)為該語言最重要的基礎。而且,λ演算的函式可以接受函式當作輸入(引數)和輸出(傳出值)。
函數語言程式設計關心型別(代數結構)之間的關係,指令式程式設計關心解決問題的步驟。函數語言程式設計中的lambda可以看成是兩個型別之間的關係,一個輸入型別和一個輸出型別。lambda演算就是給lambda表示式一個輸入型別的值,則可以得到一個輸出型別的值,這是一個計算,計算過程滿足 -等價和 -規約。函數語言程式設計的思維就是如何將這個關係組合起來,用數學的構造主義將其構造出你設計的程式
比起指令式程式設計,函數語言程式設計更加強調程式執行的結果而非執行的過程,倡導利用若干簡單的執行單元讓計算結果不斷漸進,逐層推導複雜的運算,而不是設計一個複雜的執行過程。
指令式程式設計是面向計算機硬體的抽象,有變數(對應著儲存單元),賦值語句(獲取,儲存指令),表示式(記憶體引用和算術運算)和控制語句(跳轉指令),一句話,命令式程式就是一個馮諾依曼機的指令序列。
而函數語言程式設計是面向數學的抽象,將計算描述為一種表示式求值,一句話,函式式程式就是一個表示式。
函數語言程式設計最重要的特點是“函式第一位”,即函式可以出現在任何地方,比如你可以把函式作為引數傳遞給另一個函式,不僅如此你還可以將函式作為返回值。
函數語言程式設計的本質
函數語言程式設計中的函式這個術語不是指計算機中的函式(實際上是Subroutine),而是指數學中的函式,即自變數的對映。也就是說一個函式的值僅決定於函式引數的值,不依賴其他狀態。比如sqrt(x)函式計算x的平方根,只要x不變,不論什麼時候呼叫,呼叫幾次,值都是不變的。
在函式式語言中,函式作為一等公民,可以在任何地方定義,在函式內或函式外,可以作為函式的引數和返回值,可以對函式進行組合。
純函數語言程式設計語言中的變數也不是指令式程式設計語言中的變數,即儲存狀態的單元,而是代數中的變數,即一個值的名稱。變數的值是不可變的(immutable),也就是說不允許像指令式程式設計語言中那樣多次給一個變數賦值。比如說在指令式程式設計語言我們寫“x = x + 1”,這依賴可變狀態的事實,拿給程式設計師看說是對的,但拿給數學家看,卻被認為這個等式為假。
函式式語言的如條件語句,迴圈語句也不是指令式程式設計語言中的控制語句,而是函式的語法糖,比如在Scala語言中,if else不是語句而是三元運算子,是有返回值的。
嚴格意義上的函數語言程式設計意味著不使用可變的變數,賦值,迴圈和其他命令式控制結構進行程式設計。
從理論上說,函式式語言也不是通過馮諾伊曼體系結構的機器上執行的,而是通過λ演算來執行的,就是通過變數替換的方式進行,變數替換為其值或表示式,函式也替換為其表示式,並根據運算子進行計算。λ演算是圖靈完全(Turing completeness)的,但是大多數情況,函式式程式還是被編譯成(馮諾依曼機的)機器語言的指令執行的。
函數語言程式設計的特性
-
函式是"一等公民":函式優先,和其他資料型別一樣。
-
只用"表示式",不用"語句":通過表示式(expression)計算過程得到一個返回值,而不是通過一個語句(statement)修改某一個狀態。
-
無副作用:不汙染變數,同一個輸入永遠得到同一個資料。
-
不可變性:前面一提到,不修改變數,返回一個新的值。
由於變數值是不可變的,對於值的操作並不是修改原來的值,而是修改新產生的值,原來的值保持不便。
通常來說,演算法都有遞推(iterative)和遞迴(recursive)兩種定義。
由於變數不可變,純函式程式語言無法實現迴圈,這是因為For迴圈使用可變的狀態作為計數器,而While迴圈或DoWhile迴圈需要可變的狀態作為跳出迴圈的條件。因此在函式式語言裡就只能使用遞迴來解決迭代問題,這使得函數語言程式設計嚴重依賴遞迴。
函式式語言當然還少不了以下特性:
-
高階函式(Higher-order function):就是引數為函式或返回值為函式的函式。有了高階函式,就可以將複用的粒度降低到函式級別,相對於面嚮物件語言,複用的粒度更低。
-
偏應用函式(Partially Applied Functions):一個函式接收一個有多個引數的函式,返回一個需要較少引數的函式。偏函式將一到多個引數在內部固定,然後返回新函式,返回的函式接收剩餘的引數完成函式的應用。
-
柯里化(Currying):輸入一個有多個引數的函式, 返回一個只接收單個引數的函式。
-
閉包(Closure):閉包就是有權訪問另一個函式作用域中變數的函式.閉包的三個特性:1.閉包是定義在函式中的函式 。2.閉包能訪問包含函式的變數。3.即使包含函式執行完了, 被閉包引用的變數也得不到釋放。具體參看《閒話閉包》
函數語言程式設計的好處
由於指令式程式設計語言也可以通過類似函式指標的方式來實現高階函式,函式式的最主要的好處主要是不可變性帶來的。沒有可變的狀態,函式就是引用透明(Referential transparency)的和沒有副作用(No Side Effect)。
函式即不依賴外部的狀態也不修改外部的狀態,函式呼叫的結果不依賴呼叫的時間和位置,這樣寫的程式碼容易進行推理,不容易出錯。這使得單元測試和除錯都更容易。
由於(多個執行緒之間)不共享狀態,不會造成資源爭用(Race condition),也就不需要用鎖來保護可變狀態,也就不會出現死鎖,這樣可以更好地併發起來,尤其是在對稱多處理器(SMP)架構下能夠更好地利用多個處理器(核)提供的並行處理能力。
我覺得函式程式設計的好處就不用管js裡面該死的this指向
函數語言程式設計語言還提供惰性求值-Lazy evaluation,也稱作call-by-need,是在將表示式賦值給變數(或稱作繫結)時並不計算表示式的值,而在變數第一次被使用時才進行計算。這樣就可以通過避免不必要的求值提升效能。
函數語言程式設計語言一般還提供強大的模式匹配(Pattern Match)功能。在函數語言程式設計語言中可以定義代數資料型別(Algebraic data type),通過組合已有的資料型別形成新的資料型別,如在Scala中提供case class,代數資料型別的值可以通過模式匹配進行分析。
函數語言程式設計天生親和單元測(特別是黑盒測試),因為FP關注就是輸入與輸出。反觀Java或者C++,僅僅檢查函式的返回值是不夠的:程式碼可能修改外部狀態值,因此我們還需要驗證這些外部的狀態值的正確性。在FP語言中呢,就完全不需要。
除錯查錯方面,因為FP程式中的錯誤不依賴於之前執行過的不相關的程式碼。而在一個指令式程式中,一個bug可能有時能重現而有些時候又不能。因為這些函式的執行依賴於某些外部狀態, 而這些外部狀態又需要由某些與這個bug完全不相關的程式碼通過某個特別的執行流程才能修改。在FP中這種情況完全不存在:如果一個函式的返回值出錯了,它一直都會出錯,無論你之前運行了什麼程式碼。而整個程式就是函式接龍。
推薦閱讀《傻瓜函數語言程式設計
泛型程式設計
泛型程式設計是另外一個有趣的話題。泛型為程語言提供了更高層級的抽象,即引數化型別。換句話說,就是把一個原本特定於某個型別的演算法或類當中的型別資訊抽象出來。這個抽象出來的概念在C++的STL(Standard Template Library)中就是模版(Template)。STL展示了泛型程式設計的強大之處,一出現就成為了C++的強大武器。除C++之外,C#,Java,Haskell等程式語言都引入了泛型概念。
泛型程式設計是一個稍微區域性一些的概念,它僅僅涉及如何更抽象地處理型別,即引數化型別。這並不足以支撐起一門語言的核心概念。我們不會聽到一個程式語言是純泛型程式設計的,而沒有其他程式設計正規化。但正因為泛型並不會改變程式語言的核心,所以在大多數時候,它可以很好的融入到其他的程式設計方式中。C++,Scala,Haskell這些風格迥異的程式語言都支援泛型。泛型程式設計提供了更高的抽象層次,這意味著更強的表達能力。這對大部分程式語言來說都是一道美味佐餐美酒。
在Swift中,泛型得到廣泛使用,許多Swift標準庫是通過泛型程式碼構建出來的。例如Swift的陣列和字典型別都是泛型集。這樣的例子在Swift中隨處可見。
原文連結:再談程式設計正規化-程式語言背後的思想 - 模型設計,領域設計,軟體設計, - 周陸軍的個人網站,再談系列都是搬磚總結性文章,文有不妥之處,請留言告知,多謝!
參考文章:
程式設計正規化:指令式程式設計(Imperative)、宣告式程式設計(Declarative)和函數語言程式設計(Functional)
神奇的λ演算 https://www.cnblogs.com/dragonpig/archive/2010/01/26/1657052.html
程式語言正規化 http://www.cnblogs.com/lisperl/archive/2011/11/20/2256165.html
λ 演算學習 https://www.cnblogs.com/kirohuji/p/7080876.html
函數語言程式設計漫談 https://cloud.tencent.com/developer/article/1190773
此文大多是本文給出的連結文字提煉總結,如果不妥之處,請到本站留