語言的奧祕

海興發表於2013-01-04

2012已經過去,2013剛剛開始。想起擦肩而過的末日,不禁膽寒,認認真真地補上一篇總結吧!今晚,憑悼我禍禍過的光陰!從明天起,做一個幸福的人!看書,程式設計,宅在家裡。

引子

1865年1月31日,美國眾議院,國會最激進的共和黨人撒迪厄斯·史蒂文斯沉吟半晌,環視擠滿了人群的會議廳,終於回應了紐約眾議院代表的質詢,“修正案的真正目的,只是為了法律面前人人平等”。而他此前一直在宣稱人人生而平等,黑人和白人平等。為了使第十三修正案順利通過,為了最終廢除奴隸制,他在人人生而平等前加上了“法律面前”幾個字,避開了爭論最激烈的種族平等問題。聽著樓下的辯論,樓上的林肯夫人說:“這個老傢伙居然憋了這麼久,他將來會成為一個政治家的。”

投票結束後,在走廊裡,艾薩質疑他喪失了自己的良心,居然否認自己為之奮鬥三十年的“人人生而平等”,否認黑人的權利。面對非難和質疑,史蒂文斯說出了下面這段話:“我希望修正案能通過......為了這份修正案,為了我奮鬥畢生的事業,為了那些在抗爭道路上獻身的黑人,為了千千萬萬犧牲的士兵,沒有什麼是我不敢說的,也沒有什麼是我不能說的。”

這是 史蒂文·斯皮爾伯格 2012年的新電影 林肯 裡面的一段場景。

選擇什麼語言,完全是由目的決定的,這才是語言的奧祕。真正掌握語言奧祕的,不是作家,不是相聲演員,而是政治家!好吧,也有可能是編劇。

我生命中的那些程式語言

我接觸的第一門程式語言是ANSI C,譚浩強教授的《C程式設計》賣了1000萬冊,裡面有我一本。可除了作業,我只用它做過一個程式。那是一個月黑風高的晚上,宿舍裡的兄弟們都已酣然入夢。我折騰了大半夜,用Turbo C在那臺486上一條線一條線地畫了一個視窗,滑鼠在視窗內一點選,就會以點選的座標為圓心畫一個圓。編譯執行成功後,我對著螢幕難抑內心的激動,呵呵傻笑起來。現在想起來,覺得當年自己真是傻得很有道理。

多年以後我才知道,C語言是由UNIX的研製者丹尼斯·裡奇(Dennis Ritchie)於1970年在由肯·湯普遜(Ken Thompson)發明的B語言的基礎上發展和完善起來的。除了知道它比我還老,有什麼意義?

學彙編是在C之後還是之前,我已經不太記得了。能記住的只有暫存器和MOVGOTO等有限的幾個指令了,當然還有程式碼的長度。在應用程式這種級別的開發中,恐怕除了破解,再也找不到彙編的身影了吧。

之後我接觸到了Java 1.2,也是我一直使用到現在的語言。當時為了從程式導向的思考方式轉變成物件導向的思考方式也經常跟自己較勁。為了理解多型性、封裝性和可繼承性耗費了很多腦細胞,還經常搞不清楚什麼是過載(Overload),什麼是重寫(Orverride,當年一般叫覆蓋)。但Java當時於我,不過是一門選修課而已,和她再次相遇,是在多年以後。

在大三那年的暑假,我邊學邊練,用Visual FoxPro給一家電器店做了一套簡易的進銷存系統。最後系統交付時,看著我演示的功能,老闆提出了一個讓我覺得匪夷所思的問題。他問,你這個報表的線能不能細一點,或者乾脆不用線?我懵了,他很和善地跟我解釋:“線粗費墨,墨盒也不便宜啊!”那是我第一次用專業技能做一個實用的東西,但至於後來這東西有沒有用起來,我不得而知。並且以後再也沒用FoxPro做過任何東西。哦,說到語言,它應該可以歸為SQL吧。咦,我當時寫過SQL嗎?這個真不記得了。

既然聊程式語言的時候可以說SQL,HTML應該也可以出場吧。那時候網際網路剛剛興起,Netscape正如日中天,ICQ還在國門外徘徊,OICQ也沒出父胎,在校園裡流傳的只有WPS的金山傳說。我能遇見HTML,在當時也算很時代前沿吧。雖然我征服了DHTML,可惜卻被CGI(Common Gateway Interface)這個美其名曰普通門的門攔在門外,沒能鼓搗出個網站來。不然,也許,大概,差不多,能更早認清自己是塊廢柴的現實吧 :(

javascript是我的最愛之一,我是在畢設的時候遇到它的,不過不是用它程式設計,而是要做個它的編譯器。當然,也不是完整意義上的編譯器,只是為了提取javascript程式碼中會顯示出來的字串。找到alert不難,難得是找到各種字串用機器翻譯出來。還好有Lex和YACC這樣的神器,最後,我畢設居然通過了!

工作後的第一個專案就是用JavaScript做的Web應用,前後端都是,前幾天在微博上,一前端工程師慨嘆掌握一門服務端程式語言是多麼重要,求推薦再次成功引發了一場口水戰。我不僅跟著慨嘆,大概沒幾個人記得Netscape的Serverside JavaScript了吧,古今將相今何在,荒冢一堆草沒了.....

我再次遇到Java是在它的1.5之後,算是沒遭過EJB的罪,直接跟進了Struts,所以我不恨她。之後又陸續用過Springframework,iBatis,Hibernate。啃了一段時間MyFace之後,還折騰過幾天wicket。用seam做了個專案後,又嘗試了sitebricks,最後因為Guice年紀大,bug比weld少而向sitebricks傾斜了很多。可外面又傳來了Scala的喊殺聲,揚言要滅了自己的老子Java,跟當年Java滅了C一樣讓歷史重演,所以我又看上了playframework...

這些年雖然一直以Java為主,但其間也試過Zope,用PHP搭過公司網站,用ActionScript寫過小遊戲,都是玩票的性質,沒有深入,也缺乏半夜畫線攢視窗的熱情了。

轉眼Java已經7了,Sun也步BEA的後塵歸了Oracle。想想這些年我經歷過的這些女人,咳咳,語言!以後請不要把程式語言比成女人,這不公平,謝謝!想想這些年我經歷過的這些語言,不免唏噓。這筆流水賬就像一個懵懂的人走進了一片大森林,漫無目的,全憑際遇。但其實冥冥中自有天意,這些語言之所以能來到這個世界並掙得一席之地,是由自然規律支配的(身後大廠的撐腰不容小覷,想想delphi和.net吧),它們都是語言生態系統中的一份子。

語言生態學

Java是執行時編譯、靜態型別的指令式語言。什麼意思?

程式語言也有很多種不同的風味1。或者說不同語言裡會有不同程式設計風格的烙印。弄明白這些差異很關鍵,也很有趣。

1咦,我為什麼要說也?

注意 下面的提到的分類方法只作為對語言多樣性思考的輔助。雖然有些分法更容易形成清晰的分類,但沒有完美的分類方案。

現在語言也會打破各種界限新增新特性。也就是說我們最好只說某種語言比其它語言“函式化程度更低”,而不要冒險說這種語言是函式式語言,而那種語言是指令式語言。

但我們畢竟不是政客,說話不用那麼滴水不漏,所以還是乾脆點,討論下“解釋型與編譯性”,“動態型別與靜態型別”,“指令式與函式式”語言之間差異。是的,我沒提”程式導向與物件導向“。

不同的語言可能會有不同的側重;比如動態型別的語言可能更看重部署速度。而Java則更強調安全性、程式碼清晰程度和效能,並願意接受程式碼的繁瑣性,願意放棄一定的靈活性(比如部署時)。

解釋型 vs. 編譯型語言

解釋型語言是那種原始碼中的每一步是什麼就執行什麼的語言,不會在執行開始之前把整個程式轉成機器碼。編譯型語言和它相反,用編譯器把人類可讀的原始碼變成二進位制形態被當做初始任務。

這種劃分最近變得模糊了。在80年代和90年代早期,邊界還相當清晰:C/C++及類似的語言是編譯型的,Perl和Python是解釋型語言。但Java同時兼具編譯型和解釋型兩種語言的特性。位元組碼的出現把這個問題進一步攪渾了。人類肯定讀不了位元組碼,但它也不是真正的機器碼。

動態型別 vs.靜態型別

動態型別語言關注變數包含哪類值(比如數字或字串)的資訊,而靜態型別語言關注變數的型別資訊。

靜態型別非常適合編譯型語言,因為所有型別資訊都在變數上,而不在於變數的值。所以在編譯時就可以推匯出潛在的型別系統違規行為。

動態型別語言把型別資訊放在變數所持有的值上,變數在不同的時間可能會有不同的型別。因此很難發現型別違規行為,因為變數的值要到執行時才能得到。Javascript就是最著名的動態型別語言。

指令式vs.函式式語言

指令式語言把程式的執行狀態建模為可修改資料,通過一系列指令來改變程式的執行狀態。因此,程式狀態才是指令式語言中的主角。

指令式語言主要分為兩類。一種是過程語言,比如BASIC和FORTRAN,把程式碼和資料完全分開,並且有個簡單的程式碼運算元據正規化。另外一種是物件導向(OO)語言,資料和程式碼(以方法的形態)被放在一起封在物件裡。

函式式語言的觀點與指令式語言不同,它把計算本身當做最重要的概念。函式式語言也會像過程語言一樣對資料進行操作,但它不會修改輸入的資料,而是像數學函式一樣返回新資料。

至於我經歷過的那些語言該如何歸位,我想還是再等等吧。雖然它們最初都有自己的定位,可畢竟它們還在推出各自的X版,與之配套的框架、最佳實現、工具、製成品還在不斷豐富。Java 8都要支援lambda了,保不齊Lisp清心寡慾了這麼多年後也會搞物件。你能看清楚那個一口京腔罵“電梯裡有倆2B”是個姑娘還是個人妖嗎?反正我是沒看出來。

語言金字塔

其實除了前面那種技術特性上的分類,語言還可以根據目的分層。下面這幅圖就是程式語言的金字塔:

程式語言金字塔

圖 1.程式語言金字塔

對於這三層的解釋,請看下錶:

表 1.程式語言金字塔

名稱 描述 例子
特定領域層特定領域語言。與應用領域的特定部分結合非常緊密。Apache Camel DSL, Drools,Web模板
動態層開發速度快,生產率高,功能靈活部署Groovy, Jython, Clojure
穩定層核心功能,穩定,經過良好測試,效能高Java, Scala

果然是花花公子的慧眼,讓你看出來了,上面的例子確實基本都是Java他們家的。

開篇說過了,語言的奧祕在於為達成目的巧妙安排,並無優劣之分。所以請你不要浪費時間跟人打口水仗,也沒必要求推薦讓別人打口水仗。先搞清楚自己的目的吧,畢竟此生有涯,扯皮無邊。至於該如何選擇,如何取捨,那要靠自己花時間去琢磨了。

相關文章