Andy
Andy

手民

編程自學指南番外:編程流派演義

有人的地方就有江湖,有思想的地方就有譜系,編程自然也不例外。

所謂編程,就是描述計算過程。計算應該怎樣理解,粗略分之,有兩大門派:步驟派函數派

一、步驟派

步驟派(Procedural),又譯過程派,祖師是圖靈,基礎模型是圖靈機

所謂圖靈機,是一臺想像的機器,有兩個部件:一條紙帶」一個讀寫頭(可以想像成磁帶機)。紙帶分成一個個格子,每個格子裡面寫着指令或者數據,讀寫頭按照順序讀取一個個指令或數據,一步一步執行,在紙帶上讀寫。

現代電子計算機的核心部件是CPU,CPU就是那個讀寫頭。內存就是那個紙帶。現在計算無論功能多麼神奇,其實都只是從內存裏讀數據,運算,然後再存回內存而已。

圖靈機易用電路實現。現在量產的「計算機」,就只有步驟派的機器了,其他門派思路無論如何不一樣,最後想在物理世界實現,還是要用步驟派的功夫。

步驟派之後又分爲兩支:原教旨步驟派結構派(Structural)。

結構派是步驟派裏面的革命黨。圖靈和馮・諾以曼之貢獻,在於說「指令可以當成數據存儲」。結構派則認為,「數據」和「指令」就算本質相同,寫代碼的時候,應該明確區分。指令就是指令,不應該當作數據,隨意操作,而是應該用固定的一套結構來組織(故名結構派)。

你如果在60年代學習編程,會遇到「結構化編程」(Structural programming)這個概念。這個提法,現在已經沒什麼人用了,原因很簡單:結構派大獲全勝,現在已經很少像以前一樣,一個一個格子去填代碼和數據了

結構派祖師是Algol,領軍語言是C,多年屹立不倒。今天流行的編程語言,語法上,基本都是結構派的後裔。

原教旨步驟派的代表語言是機器語言和彙編語言(Assembly),現在職業寫彙編的人已經很少了。

二、函數派

話分兩頭,圖靈發明圖靈機,開宗立派,還有一人能與之抗衡,名曰邱奇,也是數學家。

邱奇提出了一套理論,叫做λ演算Lambda calculus),跟圖靈機一樣,可以描述計算過程。

λ演算的核心模型不是讀寫紙帶,而是函數(所以叫函數派),具體來說,是「數學函數」,也就是「變量的關係」——比如,1个梨子1元,2個梨子就是2元,這是「梨子數量和總價格的關係」,也是一個函數。幾個函數可以組合成新函數,從而表達各種概念和關係。

函數派的旗幟是Lisp。上一波人工智能熱潮中,Lisp就是主力。函數派甚至有過自己的機器,叫Lisp Machine,可惜曇花一現。80年代末,AI寒冬,Lisp失勢,函數派也一蹶不振。 AI近幾年再起,主力語言已經變成Python和Java/C++了。

Lisp後代繁多,目前有兩大家:Scheme家和Common Lisp家,Scheme重純粹,Common Lisp重應用。

Lisp還有一個分家ML,此家的強項是類型理論,尤其是靜態類型加自動類型推導,成員包括Haskell和OCaml。OCaml也是奇怪,通常的趨勢是對象派語言向函數派靠攏,OCaml則是函數派主動混入對象派。OCaml在金融界應用廣泛,薪酬很高。

近些年,函數派再次崛起,因爲又找到了優勢領域:並行運算。2005年前後,CPU工藝遭遇物理學瓶頸,主頻封頂(這十年量產CPU主頻還是只有3GHz上下),要提高性能,只能向多核、多機並行運算。此外GPU也異軍突起,幾與CPU平起平坐,而GPU也是典型的並行運算設備(運算單元能力弱,但是數量多)。函數派強調純函數,隔離副作用,非常適合做並行運算,於是時來運轉,又受一部分業界的青睞。

在分佈式運算以外的領域,函數派還是有運算速度慢的軟肋。但是,現在電腦速度已經很快了,步驟派用10毫秒,慢1倍也才20毫秒,對用戶來說都是幾乎感覺不到的。函數派的思想傾向,在新語言裏已經很常見了:一等函數(無名函數、高階函數)、自動內存管理(垃圾回收)、鼓勵純函數、避免修改變量,等等。

函數派對「數據」「指令」的關係認知,倒與原教旨步驟派相似:「數據」「指令」一體二相,本應自由轉換。把「指令」當成「數據」修改的技術,美名曰「元編程」(metaprogramming)。

函數派是小衆派別,學校不教,人數少,散落各地。λ演算名字裏「λ」這個字,便是函數派的標誌,函數派弟子以此相認。

此人必定是函數派弟子

編程語言Haskell的logo

(遊戲《半衰期》的標誌也是λ,但他們的λ外面有個圓圈。)

三、對象派

步驟派和函數派之外,還有一個思潮,傳承模糊鬆散,勉強統稱爲「對象派」。

對象派的共通思路是,數據和指令還是有關係的,在代碼形式上應該體現出來。對象派是對步驟派的反動,希望重新建立數據和指令的聯繫,以此組織代碼。

粗略數來,對象派又分三支:類型宗消息宗原型宗

類型宗,顧名思義,重視「類型」(Class),喜歡研究「這個概念屬於什麼類型」、「這個類型是否包含那個類型」。類型中人寫代碼,先要研究問題領域裏面的概念,然後結一張類型網,然後一個個節點去實現。

類型宗的祖師是Simula(Simula又從Algol起步),後代有C++和Java發揚光大,流傳甚廣。類型宗是對象派的主流,你現在在網上看到的「面向對象編程」教程,基本上都是傳類型宗的道。

消息宗,始祖Smalltalk(Smalltalk師從Simula),後代有Objective-C。消息宗的核心觀點是,軟件就像生物體,應該是由半獨立的「細胞」構成,細胞之間的合作,通過消息傳遞完成,消息處理方法由收信細胞決定,而非發信細胞直接指導收信細胞。

Smalltalk創始人Alan Kay也是敲定「面向對象編程」(Object-oriented programming,OOP)一詞之人,然而據他後來說,名字取壞了,應該叫「Message-oriented programming」的。 如果他真的這麼取了,「面向對象」這張旗子可能就打不起來了。

原型宗,祖師是Self(Self是Smalltalk的後裔)。它說,刻畫結構,應該先做一個「原型」(Prototype)概念,這個原型應該可以獨立使用。其他概念再去延展這個原型,由此刻畫概念之間的關係。這一支很小眾,但有一個門徒混出來了,那就是JavaScript。JavaScript乘Web和Node.js的東風,壟斷前端,染指後端。有它在,原型派一時之間不會亡了

「面向對象編程」,80年代、90年代炒得火熱,尤其是類型雙煞C++和Java,一時無兩。類型宗提出的方案,迎合了當時軟件開發職業化、大規模化的需求,宣傳類型繼承(省錢)、模塊封裝(部門之間不用撕逼了)、設計模式(限制野雞程序員破壞力)之類的。近幾年大家發現,這派功夫並沒有吹得那麼好。類型繼承其實滿足的是「不改舊代碼,只加新代碼,就能開發新功能」的需求,但是現在敏捷開發、持續集成流行,「不用改舊代碼」並不是那麼重要。在小而精的創業團隊,工程師有全棧開發能力,很多類型宗隔離模塊的規範和模式,反而干擾開發節奏。

四、邏輯派和其他小門派

總體而言,步驟派和函數派互爲表裏,對象派是結構步驟派的支流,此三派爲當今顯學。三派之外,還有些小門派。

邏輯派

此派與函數派淵源頗深,也是從數學而來。邏輯派講究描述「邏輯關係」,例如你給出「張三是人」「凡人必死」,它能算出「張三會死」。它還有獨門祕技,「反查」:比如你說「張三是人」「李四是神」「人死神不死」,然後可以問電腦「誰會死?」,它能回答「張三」。

其他門派,當然也能做到反查,但是需要專門實現反查規則。邏輯派則可自動由數據推出。

人工智能派

以上門派,都是人來編程。現在有人在研究機器自己來編程自己,比如所謂「神經圖靈機」(Neural Turing Machine),給它大量的輸入和輸出,它會自動嘗試寫出最優的算法,攀擬輸入和輸出之內在邏輯。此派現在尚在襁褓,今後成熟,大概會革了程序員自己的命。

編程流派多,派中有派,又不斷交雜,掛一漏萬。欲知詳情,請參:

http://wiki.c2.com/?ThereAreExactlyThreeParadigms

http://www.eecs.ucf.edu/~leavens/ComS541Fall97/hw-pages/paradigms/major.html

https://en.wikipedia.org/wiki/Programming_paradigm

CC BY-NC-ND 2.0 版权声明

喜欢我的文章吗?
别忘了给点支持与赞赏,让我知道创作的路上有你陪伴。

加载中…
加载中…

发布评论