1. 程式人生 > >關於程式語言的一些趣史

關於程式語言的一些趣史

回顧歷史做仔細的分析與研究,總能給人意想不到的發現和驚歎。從認知的難易程度上來看,程式語言的正規化可以按照如下的方式排序:最容易理解的是structured programming,一根線從上往下;再來會稍微費點功夫理解的是object-oriented(OO)programming;更困難的是functional programming,相當抽象,整個就是一數學的抽象思維。

自然地,歷史的發展都是由簡單到複雜,我們會下意識地認為程式語言在歷史上的出現順序也應該是:structured programming、OO、functional programming。

但翻閱歷史,卻會驚訝地發現它們的出現順序竟然是反過來的!

  • structured programming是在1968年出現,其標誌是Dijkstra(對,那個最短路徑演算法裡出現的名字)發表他的seminal paper 'Cooperating sequential processes’。

  • 再來是更早的1966年,Dahl和Nygaard發現function call stack frame可以被放到heap去做,這標誌著OO的出現。

  • 而似乎最難以理解的functional programming,則幾乎可以追溯到1936年計算機被髮明的時期。其標誌是Alonzo Church推出lambda calculus。

另一件值得探討的事情是:為什麼Dijkstra要引入structured programming?雖然從現在來看structured programming是如此的直觀,以至於你會問,為什麼會過了那麼久才引入structured programming?

在Dijkstra的時代,主流程式語言都不是structured的,到處充斥著goto所帶來的跳轉。為什麼會遍地的goto呢?因為在計算機語言的莽荒時期,一切都是向機器看齊的。對於機器語言、彙編來講,指令集的各種jump操作是再平常不過的事情了。既然它們都有之靈跳轉,對應的程式語言怎麼好意思說不支援goto呢?

所以,structured programming反而在當時是一種極端的非主流,因為它為programming給予了相當大的限制。

Dijkstra之所以要引入structured programming源自於他要把“計算機”這門學科變為科學的嘗試:將數學的公理化體系引入computer science(CS)。但經過大量嘗試後,他發現要為程式碼構建牢固的數學公理體系著實不是一件容易的事情。而其中最大的問題障礙,就是goto帶來的不確定性。

於是,Dijkstra採用了數學家常用的研究方法:當需要推出一個漂亮的理論卻發現前提條件不夠時,就反過來先引入這個結論需要的前提假設。

於是,Dijkstra就直接把goto(至少是被濫用的goto)廢除掉。沒有了goto,雖然引入數學的嚴格證明會變得相當簡單,但這樣會不會限制語言的表達?又或者說,有些程式碼是不是沒有了goto就無法寫出來呢?

說來也是歷史機緣,恰好在這個時候,Bohm and Jacopini在理論上證明了:所有的程式都可以被以下三種句式所替代: sequence, selection(if/then/else), iteration(for/while)。而這正好是Dijkstra所需要的,因為實現這三種語句完全用不到goto。於是,Dijkstra的為CS引入嚴格數學公理體系的壯舉也就水到渠成:所有的由sequence、selection(if/then/else)語句構成的程式,可以由數學列舉法證明。而由iteration(for/while)語句構成的程式,則可以由數學歸納法完成。而structured programming這種被做了更多限制的程式設計正規化也就應運而生。(很有意思的事情是,三種程式設計正規化structured programming、OO、functional programming的引入,都是通過“限制功能”而非增加功能做出的,也即是,為了更強你需要更弱一點。更多討論可以參考我以前的一篇文章《為了快一點為什麼卻要慢一點》。)

如果按照這樣的思維框架去思考演算法,比如LeetCode中的演算法題目,又會有一些驚人發現。我的一個想轉行做程式設計師的朋友曾跟我聊過這樣一段刷題感受:似乎演算法題目都或多或少地在使用數學歸納法。這確實是很強的洞見。回顧起來,無論是divide-and-conquere還是dynamic programmming,這兩種作為演算法基石的工具都運用到了數學歸納法的思維方式。前者(遞迴)是天然的數學歸納法處理方式,而後者則是做了空間複雜度優化的遞迴,同樣按照數學歸納法的方式做處理。

進一步,我們可以考察一些工作中遇到的問題。剛畢業工作的小白程式設計師常常會疑惑這樣一個事情,明明自己在學校中演算法的造詣頗高,按道理說演算法好不就是程式設計的功底好麼,但為什麼到了工作崗位中還是各種碰壁?

按照我們上面構建的思維框架,我們其實可以給出一種解釋:因為演算法部分的修煉,僅僅保證了你在structured programming這個語言正規化下做事具備了很好的能力。可工作中所涉及到的軟體設計,則是在OO正規化和functional programming正規化下進行的。領域不同,自然是新手,碰壁也是自然之事。

再回到我們最開始的那個問題,為什麼程式設計正規化會是以相反的認知方向來發展?因為這是按照“構建計算機領域”的難易程度在走,也即是背後的數學發展在展開,而不是程式語言使用的難易程度在發展。這是一門新興學科初期的發展特點——先考慮的是生產的便利性,再來是消費者的便利性。

========

Comments for 《Clean Architecture》

近期回顧

如果你喜歡我的文章或分享,請長按下面的二維碼關注我的微信公眾號,謝謝!

更多資訊交流和觀點分享,可加入知識星球: