日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

“主要的编程范型”及其语言特性关系(多图)

發(fā)布時間:2025/3/21 65 豆豆
生活随笔 收集整理的這篇文章主要介紹了 “主要的编程范型”及其语言特性关系(多图) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

“主要的編程范型”(The principal programming paradigms)這幅圖,其實出現(xiàn)得不算早,作者在2007年完成了該圖的1.0版,到2008年更新至v1.08版本。本次提供的是翻譯成中文的版本(老實說,筆者翻譯水平相當(dāng)有限,若有不當(dāng)之處,請各位盡量指出,必盡快補(bǔ)正)。

?

這幅圖的原作者Peter Van Roy,是《Concepts, Techniques, and Models of Computer Programming》一書的作者,這本書(CTM)是少有的、能跟SICP并稱的書了。

?

 

該圖原文檔(PDF)下載:

http://www.info.ucl.ac.be/~pvr/paradigmsDIAGRAMeng108.pdf

?

該圖中文翻譯文件(PDF)下載:

http://www.delphibbs.com/keylife/images/u40/paradigmsDIAGRAMeng108_CN.zip

?

?

圖:主要的編程范型(點擊看大圖)

?

(圖1)主要的編程范型-縮略圖

 

?

一、從數(shù)據(jù)到編程
======

Peter在“主要的編程范型”中,首先分清了數(shù)據(jù)描述語言與描述式編程語言。他把數(shù)據(jù)描述語言——例如XML——作為獨立部分劃分出來,然后指出這類語言主要考慮數(shù)據(jù)結(jié)構(gòu)的描象,理論上基于人們對結(jié)構(gòu)(記錄/Record、結(jié)構(gòu)/Struct)的理解。接下來,作者在此基礎(chǔ)上引入第一種“程序設(shè)計特性”,即procedure,由此得到“初階函數(shù)式編程”這一個基本的程序設(shè)計范型。

?

從這里可見Peter在程序設(shè)計語言分類上與以前的其它方法的不同之處:Peter并不在乎語言出現(xiàn)的時間關(guān)系,也不在乎語言的流行程度的影響。他著力于觀察語言特性發(fā)展之間的脈絡(luò)。而必須要對上述內(nèi)容補(bǔ)充說明的是,Peter在“初階函數(shù)式編程”所說的函數(shù),事實上是早期業(yè)界對“函數(shù)(function)”的定義,即:例程分為過程、函數(shù)兩種,二者區(qū)別僅在于前者不返回值,后者返回值。所以事實上,在這里Peter強(qiáng)調(diào)的是一種“普通例程”的特性。

?

 

二、最重要的分類依據(jù):cells(state)
======
接下來,Peter將一個最重要的概念"state"引入進(jìn)來。而這個state也是Peter對語言進(jìn)行分類并考察它們的進(jìn)化變化的主要依據(jù)。但是,Peter所引用的這個state概念,以及在這里使用的專用名詞“cells”相當(dāng)?shù)亓钊嗣曰?#xff0c;所以在這個圖的補(bǔ)充說明中,Peter對此專門做了解釋:“狀態(tài)是記憶信息的一種能力,更精確地說,是及時存貯值序列的能力。”

?

你覺得這個概念象什么?對了,的確,非常象是“變量”。事實上,狀態(tài)在編程核心概念的“數(shù)據(jù)-邏輯”抽象中,它表明的正是“數(shù)據(jù)的可變性”,亦即是說:數(shù)據(jù)的可變性表現(xiàn)為狀態(tài)。更進(jìn)一步地說:當(dāng)數(shù)據(jù)被命名時,它稱為變量或常量;當(dāng)數(shù)據(jù)未命名時,它成為游離的、無名稱和時序含義的存儲單元,即“cells”。這也是Peter使用“cells”這個專用名詞的原因:在本圖的討論中,需要從“變量/常量”這樣的概念中,剝離掉“未命名或命名的、確定的或非確定的,以及串行的或并發(fā)的”這三方面的性質(zhì)。

?

當(dāng)不考慮一個存儲位置上的命名特性時,它就既非變量、常量,也非某個確定的運算對象(例如“對象”等高級的抽象概念),而只是一種更加泛義的“狀態(tài)”,而存儲這個狀態(tài)本身的,則因為沒有位置、時序等概念,而稱為“cells”。

 

 
三、命令式語言的誕生:狀態(tài)維護(hù)
======

《程序設(shè)計語言》這本書解釋過命令式語言的本質(zhì)特性,即:用算法改變數(shù)據(jù)。如果用兩個以上的邏輯(例如兩行代碼)去影響同一個存儲位置(cells),并使它的狀態(tài)改變,最終在該cell產(chǎn)生運算結(jié)果的,那么它就是一種命令式語言。

?

再簡單一點(但沒有上面這樣嚴(yán)謹(jǐn))地說:在程序中不斷地重寫變量,變量值即是程序的最終結(jié)果。

所以,在本圖中,Peter把這個衍生關(guān)系表達(dá)為:命令式=純數(shù)據(jù)+算法+狀態(tài)維護(hù)。如圖:

 

 

(圖2)命令式語言的誕生

 

 
四、在命令式編程中對“狀態(tài)”的理解:共享狀態(tài)
======

無論是在串行的,還是并發(fā)的編程中,命令式編程范型對“狀態(tài)”的理解都是:共享狀態(tài)。在圖中,這一分支表現(xiàn)為全部的桃紅色(參見后圖)。

?

在串行(例如單線程)的編程中,狀態(tài)是時序相關(guān)的。因為不斷地重寫“狀態(tài)(數(shù)據(jù)/cells/變量)”,所以前一行和后一行所面對都是同一個共享狀態(tài)的不同的值/副本。在這個過程中,狀態(tài)是時序相關(guān)的,所以前一分鐘與后一分鐘的狀態(tài)是不確定的——但是在同一時刻,這個狀態(tài)是確定的。

?

與上面類似的,在多線程中,同一時刻,不同線程也將面臨這個值/副本。但是正是因為多線程(并發(fā))中,線程A與線程B對于同一個cell,在同一時刻所得到的狀態(tài)也是不確定的——我們可以假想為多核CPU在對同一個內(nèi)存地址讀寫(于是就出現(xiàn)了我們所謂的“同步”問題,進(jìn)而也就出現(xiàn)了“鎖”的問題),所以在這個分支中,當(dāng)加入“線程”概念之后,新的編程范型,全都變成了“觀測-非確定性”為“yes”的情況。

 

?

?

(圖3)觀測-非確定性(留意圖中加粗的黑框),以及狀態(tài)的共享

?

 

“觀測-非確定性(Observable nondeterminism)”可以被譯為“測不準(zhǔn)”,但是用在中文中依然拗口,所以我選擇了直譯。在Peter的書(CTM)中,對該問題有一個經(jīng)典的示例,即:
------------------------
declare
? C={NewCell 0}

thread
? C:=1
end

thread
? C:=2
end
------------
Peter這段代碼的意思是說:當(dāng)線程1和線程2,在同時向C這個cell寫數(shù)據(jù)時,你并不確知上述代碼運行之后C這個位置上的值究竟是1,還是2。

 
五、解決這個問題的終極之道:不要寫cell!
======
我們顯然發(fā)現(xiàn),問題是因為多個線程都在“寫cell”。在命令式的解決方案中,采用的方法是“加鎖”;持鎖存取的最經(jīng)濟(jì)的方法之一是“多讀單寫”——即保證同時只有一個線程能“寫cell”。

?

但是這給應(yīng)用帶來了負(fù)擔(dān)——如果一個應(yīng)用程序由多個線程(分布或不分布在多個CPU核上),在它們都要讀取同一個cell、而又有某個線程要寫該cell的時候,那么大家就都要掛起來等這個寫操作完成了。整個應(yīng)用程序在CPU使用(或者說效率)上就大大地打了折扣。

?

如果這只是一個桌面程序(例如記事本),大概沒人會說什么。但如果是服務(wù)器程序(例如Web Server),那么整個網(wǎng)絡(luò)、所有的會話就都處于等待狀態(tài)了——而這個時候,服務(wù)器的CPU占用還可能遠(yuǎn)遠(yuǎn)地小于1%!

?

解決問題的終極方法,就是不解決這個問題——寫cell帶來了問題,那么我們就“不寫cell”。我們由前面所有講述的內(nèi)容開始倒推,問題根本是由“命令式語言”這個編程范型本身決定的:用算法改變數(shù)據(jù)。

所以,我們回到了原始的問題:如果算法不改變cell(數(shù)據(jù)/狀態(tài)/變量)呢?

?

 

六、函數(shù)式編程的核心概念:閉包
======

當(dāng)“過程(初階的函數(shù))”引入了“閉包”的概念后,整個“函數(shù)式語言”的體系建立了起來。所謂“閉包”,是指在函數(shù)運行的上下文中,所有的cells與函數(shù)之外無關(guān),這些cells的狀態(tài)僅與函數(shù)——這個運算邏輯相關(guān),則這個上下文環(huán)境“整體地”被稱為“閉包”。

?

如果換個說法,閉包就是不受函數(shù)之外影響的一堆cells。一般在實現(xiàn)它的時候,就是讓函數(shù)持有一個“專屬的(!)”內(nèi)存塊,并且這個內(nèi)存塊僅當(dāng)函數(shù)本身失效的時候,才被釋放。

?

一個“函數(shù)本身”何時失效呢?如果這個函數(shù)只有傳入?yún)?shù)和傳出值的功能,那么這個函數(shù)就在它傳出值之后立即失效了。所以,對于整個運算邏輯——這個函數(shù)來說,它沒有操作過任何(函數(shù)之外的)狀態(tài),既沒有讀,也沒有寫。對于這個邏輯來說,只有傳入,也只有傳出,所以它具有完全的運算確定性,它本身作為一個“結(jié)果值”來看的時候,也是確定的。

?

不過在實用時,對于上述的觀念做出了一些挑戰(zhàn)。例如說:當(dāng)函數(shù)內(nèi)部執(zhí)行了一半的時候退出,怎么辦呢?答案是:1、先不釋放函數(shù);2、過一會兒再進(jìn)入。這個,就是所謂的延續(xù)(Continuation),以及在JavaScript 1.6以后推出的yield概念。同樣的,正因為“的確存在”執(zhí)行之后函數(shù)不釋放的可能性,所以函數(shù)式語言通常是由語言引擎來維護(hù)閉包的生存周期的——任何新的概念、理論的提出,都必須保證這個生存周期可測、可維護(hù)。因此相較于命令式語言,自動內(nèi)存管理在函數(shù)式語言中實現(xiàn)起來更為高效和簡潔,它最早被實現(xiàn)在函數(shù)式語言(LISP)語言中,也是有其必然性的了。

?

這樣一來,對于在函數(shù)之外的狀態(tài)state來說,函數(shù)從來不去影響它們。函數(shù)式編程范型帶來了新的模式:給函數(shù)數(shù)據(jù)(入口參數(shù)),函數(shù)給出結(jié)果(返回值)。即通過不斷地函數(shù)運算來產(chǎn)生結(jié)果,而不改變cell(數(shù)據(jù)/狀態(tài)/變量)。

?

函數(shù)式與命令式范型相比較,前者被人稱為(P,D;I,O),后者被人稱為(I,O;P,D),其中:輸入(I)、輸出(O)、加工處理程序(P)和存儲狀態(tài)數(shù)據(jù)(D)。即函數(shù)式先明確(P,D)——確定的處理與數(shù)據(jù)(閉包),然后討論在閉包上的I、O問題。而命令式先確定了I、O的方式——即state的存取問題,然后討論P、D的設(shè)計。

 
七、狀態(tài)的命名:變量、常量、端口等
======

在整個這個“主要的編程范型”圖中,也許最接近現(xiàn)實世界(通用應(yīng)用開發(fā))而又是純函數(shù)式范型的語言,就是erlang了。從圖中的標(biāo)注來看,erlang具有這樣的一些語言特性:
1、消息傳遞
2、命名狀態(tài)
3、端口
4、閉包
5、線程(erlang中的輕量級進(jìn)程)

?

這五個特性,其實都可以歸結(jié)為erlang對“狀態(tài)”的處理方式。其中:
1、當(dāng)跨節(jié)點傳遞狀態(tài)時,采用“端口+消息傳遞”;
2、當(dāng)跨線程(進(jìn)程)傳遞狀態(tài)時,采用“進(jìn)程ID+消息傳遞”;
3、當(dāng)在多個函數(shù)/執(zhí)行過程中傳遞狀態(tài)的,采用“閉包(函數(shù)入口參數(shù))”。

亦即是說,你可以把“端口、進(jìn)程標(biāo)識或函數(shù)入口參數(shù)”想像成“一個傳送狀態(tài)的通道”,或者干脆是用于讀取其它外部代碼的“狀態(tài)的一個副本”的途徑。?

(圖4)狀態(tài)的命名

 

?

對于上述特性,erlang在整個過程中允許為狀態(tài)命名(全局的或局部的)——變量。但是,該變量只能一次賦值——向端口和進(jìn)程ID傳遞消息是一次性的,而函數(shù)參數(shù)上的變量賦值/匹配也是一次性的。盡管對狀態(tài)“是否已賦值”需要進(jìn)行有效性檢測,從而給系統(tǒng)帶來風(fēng)險,但也是使得程序可讀性和應(yīng)用性能變得“稍微好一些”的唯一方式。

?

在“主要的編程范型”圖中,緣于erlang對“命名的狀態(tài)”的取舍,它被歸為了“更少的說明式特性”的范疇。但同樣的原因,它也是我們目前“(相對)最易用”的工業(yè)級的純函數(shù)式語言。

?

同樣,在這個分支上還有一個后起之秀,就是“對象能力編程”。這在最近的報道中,已有基于Scala的Actor模型進(jìn)行的實現(xiàn)。盡管Scala是在Java上的一個實現(xiàn),但它擁有完整的函數(shù)式語言特性,并使用了面向?qū)ο蟮囊恍┱Z法與思想,在加入“對象能力類型(Object Capability Types,OCT)”之后,它擁有了跨Actor傳遞對象(整個對象可以視為一個狀態(tài)/cell)的能力——在必要的時候,目標(biāo)Actor會將接收到的對象再次本地化(local cell)。

 
八、語言的底本:LISP/Scheme/Haskell, Prolog, Fortran/Pascal, ML
======

從語言沿革的進(jìn)化關(guān)系來看,Fortran位于高級語言的基底位置,基本上來說,它是現(xiàn)今絕大多數(shù)過程式/命令式語言的底本,在這個分支上主要發(fā)展的有Algol、Simula、Pascal與C。后來出現(xiàn)的各種面向?qū)ο缶幊陶Z言,主要受到Simula跟Smalltalk的影響。

?

從Fortran之后,LISP成為所有函數(shù)式語言的底本,但由于早期LISP的應(yīng)用性極差,所以Scheme吸取了Algol與LISP的一些特性,成為函數(shù)式語言發(fā)展的主要力量之一。在1987年之后,從Scheme、Smalltalk等演化出來的Haskell,也成為不可小視的新生力量。

 

?

(圖5)函數(shù)式語言的龐大家族

 

?

Prolog這個語言的獨特的開創(chuàng)性在于:它主要描述通過邏輯事實進(jìn)行推論并得出結(jié)論的過程,它的運算對象并非直接含義上的“數(shù)據(jù)”,而是一種接近人的思維的抽象:邏輯子句。這種新的、對數(shù)據(jù)的抽象開啟了一個語言分支。

?

在圖中幾乎總是與Scheme一起出現(xiàn)的ML(Meta Language)是一種,它的一個比較普及的、方言化的實現(xiàn)是SML(Standard ML)。在這個語言分支上,一個更晚出現(xiàn)而又頗富盛名的語言是Caml/OCaml(Caml, Categorical Abstract Machine Language)。基本上,它看起來象是在ML的函數(shù)式語言特性上加上:
1、命名(持久性常量)
2、cell

Objective Caml (OCaml)支持面向?qū)ο缶幊?#xff0c;而使它更為眾所周知的是:ECMAScript Ed4(Javascript 2)的標(biāo)準(zhǔn)規(guī)范,是采用OCaml這個語言來“定義”——并同時實現(xiàn)的。而微軟的F#也是基于OCaml在函數(shù)式語言上方向上發(fā)展的。

?

另一個函數(shù)式的分支是數(shù)據(jù)流編程,它的底本語言是Dataflow——圖中出現(xiàn)的Pipes/MapReduce是兩種不同的機(jī)制,而非確定的語言。在這個分支上,現(xiàn)實中主要采用數(shù)據(jù)流編程范型的語言其實是LabVIEW。相對于數(shù)據(jù)流(驅(qū)動的)編程來講時,命令式語言也被稱為控制流(驅(qū)動的)編程語言。數(shù)據(jù)流編程在函數(shù)式這個分支中也是有開創(chuàng)意義的,它帶來了圖化、網(wǎng)絡(luò)圖化編程這樣一種格局。

?

在這一小節(jié)(以及圖)里面,主要提及到的底本語言的出現(xiàn)時間為:
??? * 1957 FORTRAN
??? * 1958 ALGOL
??? * 1960 LISP
??? * 1962 SIMULA
??? * 1969 Smalltalk
??? * 1970 Prolog
??? * 1971 Dataflow
??? * 1972 C
??? * 1973 ML
??? * 1975 Pascal
??? * 1975 Scheme
??? * 1990 Haskell?
??? * 1996 OCaml

  

九:延伸閱讀
======

《象大師們一樣思考》
http://blog.csdn.net/aimingoo/archive/2008/10/09/3037952.aspx
 

《世界需要一種什么樣的語言》
http://blog.csdn.net/aimingoo/archive/2009/03/12/3983975.aspx

 

《表面的簡潔》
http://blog.csdn.net/aimingoo/archive/2009/04/22/4099931.aspx

 ?

《無廢話JavaScript》(上)(下)
http://blog.csdn.net/aimingoo/archive/2008/10/06/3022379.aspx

http://blog.csdn.net/aimingoo/archive/2008/10/06/3022409.aspx


from:?http://blog.csdn.net/aimingoo/article/details/4648284

總結(jié)

以上是生活随笔為你收集整理的“主要的编程范型”及其语言特性关系(多图)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。