編程語言的發(fā)展趨勢及未來方向_第1頁
編程語言的發(fā)展趨勢及未來方向_第2頁
編程語言的發(fā)展趨勢及未來方向_第3頁
編程語言的發(fā)展趨勢及未來方向_第4頁
編程語言的發(fā)展趨勢及未來方向_第5頁
已閱讀5頁,還剩4頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、編程語言的發(fā)展趨勢及未來方向程序設(shè)計離不開編程語言,但是編程語言在國內(nèi)的大環(huán)境中似乎一直是個 二等公民。國內(nèi)的計算機(jī)教育和工程培訓(xùn),似乎一直在宣傳“語言不重要,重要的是思想","語言一通百通”等觀點,甚至在許多人眼中"語言的討論"完全是不 入流的,但其實"編程語言"與"工具"、"框架"或是"開發(fā)方法”等事物一樣,都 對生產(chǎn)力有著重要的影響。事實上,語言的發(fā)展歷史比其他方面更為悠久,并 且在過去十幾年,甚至最近幾年中都依然在不斷的碰撞,演變。期間一些新的 語言誕生了,而另一些在當(dāng)時看來陽

2、春白雪的語言和編程范式也重新獲得了人 們的重視。Anders Hejlsberg 是微軟的Technical Fellow ,擔(dān)任C#8程語言的首席 架構(gòu)師,也參與了 .NET Framework,以及VB.NET F#?語言的設(shè)計與開發(fā)。 幾個月前,Anders在比利時的TechDays 2010及荷蘭DevDays 2010分別進(jìn)行 了一場演講,闡述了他眼中對于編程語言的發(fā)展趨勢及未來方向,本文便對他 的觀點進(jìn)行了總結(jié)。大約25到30年前,Anders開發(fā)了著名的Turbo Pascal ,這是一套集語言、 編譯器及開發(fā)工具于一體的產(chǎn)品,這也是 Anders進(jìn)入編程語言這一領(lǐng)域的起點。 A

3、nders談到,如今的計算機(jī)和當(dāng)年他開發(fā)的 Turbo Pascal所用的Z-80已經(jīng)不 可同日而語。從那時算起,如今的機(jī)器已經(jīng)有大約10萬倍的外部存儲容量,1萬倍的內(nèi)存大小,CPUS度也有大約1000倍的提高。但是,如果我們比較如今 的Java代碼及當(dāng)年P(guān)ascal代碼,會發(fā)現(xiàn)它們的差別其實并不大。Anders認(rèn)為編程語言的發(fā)展非常緩慢,期間當(dāng)然出現(xiàn)了一些東西,例如面向?qū)ο蟮鹊龋?是遠(yuǎn)沒有好上1000倍。事實上,近幾十年來的努力主要體現(xiàn)在框架及工具等方 面(如下圖)。例如.NET Framework里有超過一萬個類及十萬個方法,與 Turbo Pascal相比的確有了超過1000倍的增長。

4、同樣類似,現(xiàn)在的IDE包含了無數(shù) 強大的功能,例如語法提示,重構(gòu),調(diào)試器等等。與此相比,編程語言的改進(jìn) 的確很不明顯。在過去5、60年的編程歷史中,編程語言的抽象級別不斷提高,人們都在 努力讓編程語言更有表現(xiàn)力,這樣我們可以用更少的代碼完成更多的工作。我們一開始使用匯編,然后使用面向過程的語言 (如Pascal和C),然后是面向?qū)?象語言(如C+),隨后便進(jìn)入了托管時代,語言運行于受托管的執(zhí)行環(huán)境上(如C#, Java),它們的主要特性有自動的垃圾收集,類型安全等等。Anders認(rèn)為這樣的趨勢還會繼續(xù)保持下去,我們還會看到抽象級別越來越高的語言,而語 言的設(shè)計者則必須理解并預(yù)測下一個抽象級別是

5、什么樣子的。另一方面, 如.NET, Java等框架的重要性提高了許多,編程語言往往都傾向于構(gòu)建于現(xiàn)有 的工具上,而不會從頭寫起。現(xiàn)在出現(xiàn)的編程語言,例如F#,以及Java領(lǐng)域的Scala , Clojure等等,它們都是基于現(xiàn)有框架構(gòu)建的,每次從頭開始的代價 頭在太Hj 0在Anders眼中,如今影響力較大的趨勢主要有三種(如下圖),它們分別是 ”聲明式的編程風(fēng)格"(包括”領(lǐng)域特定語言"及"函數(shù)式編程”)、過去的五年非常 火熱的"動態(tài)語言"(其最重要的方面便是"元編程”能力)以及多核環(huán)境下的"并發(fā) 編程。此外隨著語言的發(fā)展

6、,原本常用的“面向?qū)ο?quot;語言,"動態(tài)語言"或是"函 數(shù)式”等邊界也變得越來越模糊,例如各種主要的編程語言都受到函數(shù)式語言的 影響。因此,"多范式"程序設(shè)計語言也是一個愈發(fā)明顯的趨勢。聲明式編程與DSL目前常見的編程語言大都是命令式(Imperative)的,例如C#, Java或是 C+將等。這些語言的特征在于,代碼里不僅表現(xiàn)了"做什么(What)”,而更多表現(xiàn)出”如何(How)完成工作”這樣的實現(xiàn)細(xì)節(jié),例如for循環(huán),i+=1等等,甚至 這部分細(xì)節(jié)會掩蓋了我們的“最終目標(biāo)"。在Anders看來,命令式編程通常會讓

7、 代碼變得十分冗余,更重要的是由于它提供了過于具體的指令,這樣執(zhí)行代碼 的基礎(chǔ)設(shè)施(如CLR JVM股有太多發(fā)揮空間,只能老老實實地根據(jù)指令一步 步的向目標(biāo)前進(jìn)。例如,并行執(zhí)行程序會變得十分困難,因為像"執(zhí)行目的”這樣更高層次的信息已經(jīng)丟失了。因此,編程語言的趨勢之一,便是能讓代碼包 含更多的"What",而不是"How",這樣執(zhí)行環(huán)境便可以更加聰明地去適應(yīng)當(dāng)前的 執(zhí)行要求。關(guān)于聲明式的編程風(fēng)格,Anders主要提出了兩個方面,第一個方面是 DSL(Domain Specific Language ,領(lǐng)域特定語言)。DSL不是什么新鮮的玩意兒,

8、 我們平時經(jīng)常接觸的SQL CSS正則表達(dá)式等等都屬于 DSL)有的DSL可能更加專注于一個方面,例如 Mathematica, LOG你等。這些語言的目標(biāo)都是特定 的領(lǐng)域,與之相對的則是 GPPL(General Purpose Programming Language ,通 用目的編程語言)。Martin Fowler將DSL分為外部DSLM內(nèi)部DSL兩種。外部 DSL有自己的特定語法、解析器和詞法分析器等等,它們往往是一種小型的編 程語言,甚至不會像GPPL樣需要源文件。與之相對的則是內(nèi)部 DSL內(nèi)部 DSL其實更像是種別稱,它代表一類特別 API及使用模式。XSLT SQ導(dǎo)等都可以算作

9、是外部DSL1外部DSL一般會直接針對特定的領(lǐng) 域設(shè)計,而不考慮其他方面。James Gosling曾經(jīng)說過:每個配置文件最終都 會變成一門編程語言。一開始您可能只會用它表示一點點東西,慢慢地您便會 想要一些規(guī)則,而這些規(guī)則則變成了表達(dá)式,后來您可能還會定義變量,進(jìn)行 條件判斷等等,而最終它就變成了一種奇怪的編程語言,這樣的情況屢見不鮮。 現(xiàn)在有一些公司也在關(guān)注DSL的開發(fā)。例如以前在微軟工作的 Charles Simonyi 提出了 Intentional Programming的概念,還有 JetBrains 公司提供的一個叫做 MPS(Meta Programming System)的產(chǎn)

10、品。最近微軟也提出了自己的 Oslo項目,而在Eclipse世界里也有Xtext ,所以其實如今在這方面也有不少 人在嘗試。由于外部DSL的獨立性,在某些情況下也會出現(xiàn)特定的工具,輔助 領(lǐng)域?qū)<一蚴情_發(fā)人員本身編寫 DSL代碼。還有一些DSL會以XMLT言的形式 提出,利用XML方言的好處在于有不少現(xiàn)成的工具可用,這樣可以更快地定義 自己的語法。而內(nèi)部DSL正像之前提到的那樣,它往往只是代表了一系列特別的API及使用模式,例如LINQ查詢語句及Ruby on Rails中的Active Record 聲明代 碼等等。內(nèi)部DSL可以使用一系列API來"偽裝”成一種DSL它往往會利用一

11、些“流暢化”的技巧,例如像jQuery那樣把一些方法通過"點"連接起來,而另一 些也會利用元編程的方式。內(nèi)部 DSL還有一些優(yōu)勢,例如可以訪問語言中的代 碼或變量,以及利用代碼補全,重構(gòu)等母語言的所有特性。DSL的可讀性往往很高。例如,要篩選出單價大于20的產(chǎn)品,并對所屬種類進(jìn)行分組,并降序地列出每組的分類名稱及產(chǎn)品數(shù)量。如果是用命令式的編 程方式,則可能是這樣的:Dictionary string,Grouping groups=new Dictionary string,Grouping() ; foreach(Product pin products)if(p.Uni

12、tPrice=20)if( !groups.ContainsKey(p.CategoryName)Grouping r=new Grouping。;r.CategoryName=p.CategoryName ; r.ProductCount=0 ;groupsp.CategoryName=r ; groupsp.CategoryName.ProductCount+ ; L ist Grouping result=new List Grouping(groups.Values);result.Sort(delegate(Grouping x,Grouping y)return x.Product

13、Count y.ProductCount?-1 : x.ProductCount y.ProductCount?1 : 0; ) ; /pre顯然 這些代碼編寫起來需要一點時間,且很難直接看出它的真實目的,換言之 “What"幾乎完全被"How”所代替了。這樣,一個新的程序員必須花費一定時間才 能理解這段代碼的目的。但如果使用LINQ,代碼便可以改寫成:prevarresult=products.Where(p=p.UnitPrice=20).GroupBy(p=p.CategoryName).Ord erByDescending(g=g.Count().Select(g=

14、newCategoryName=g.Key,ProductCo unt=g.Count() ; /pre這段代碼更加關(guān)注的是"What"而不是"How",它不會 明確地給出過濾的“操作方式",也沒有涉及到創(chuàng)建字典這樣的細(xì)節(jié)。這段代碼 還可以利用C#3.0中內(nèi)置的DSL即LINQ查詢語句來改寫:prevar result=from pin products where p.UnitPrice=20 group pby p.CategoryName into gorderby g.Count()descending select newCatego

15、ryName=g.Key,ProductCount=g.Count() ; /pre編譯器會簡單地 將LINQ差距語句轉(zhuǎn)化為前一種形式。這段代碼只是表現(xiàn)出最終的目的,而不是 明確指定做事的方式,這樣便可以很容易地并行執(zhí)行這段代碼,如使用PINQ則幾乎不需要做出任何修改。函數(shù)式編程Anders提出的另一個重要的聲明式編程方式便是函數(shù)式編程。函數(shù)式編程 歷史悠久,它幾乎和編程語言本身同時誕生,如當(dāng)年的LISP便是個函數(shù)式編程語言。除了 LISP以外還有其他許多函數(shù)式編程語言,如 APL Haskell、ML等 等。關(guān)于函數(shù)式編程在學(xué)術(shù)界已經(jīng)有過許多研究了,大約在 5到10年前許多人 開始吸收和整理

16、這些研究內(nèi)容,想要把它們?nèi)谌敫鼮橥ㄓ玫木幊陶Z言。現(xiàn)在的 編程語言,如C供Python、Ruby、Scala等等,它們都受到了函數(shù)式編程語言 的影響。使用命令式編程語言寫程序時,我們經(jīng)常會編寫如x=x+1這樣的語句,此時我們大量依賴的是可變狀態(tài),或者說是“變量”,它們的值可以隨程序運行而 改變。可變狀態(tài)非常強大,但隨之而來的便是被稱為 “副作用"的問題,例如一 個無需參數(shù)的void方法,它會根據(jù)調(diào)用次數(shù)或是在哪個線程上進(jìn)行調(diào)用對程序 產(chǎn)生影響,它會改變程序內(nèi)部的狀態(tài),從而影響之后的運行效果。而在函數(shù)式 編程中則不會出現(xiàn)這個情況,因為所有的狀態(tài)都是不可變的。事實上對函數(shù)式 編程的討論更像

17、是數(shù)學(xué)、公式,而不是程序語句,如x=x+1對于數(shù)學(xué)家來說,似乎只是個永不為真的表達(dá)式而已。函數(shù)式編程十分容易并行,因為它在運行時不會修改任何狀態(tài),因此無論 多少線程在運行時都可以觀察到正確的結(jié)果。假如兩個函數(shù)完全無關(guān),那么它 們是并行還是順序地執(zhí)行便沒有什么區(qū)別了。當(dāng)然,現(xiàn)實中的程序一定是有副 作用的,例如向屏幕輸出內(nèi)容,向 Socket傳輸數(shù)據(jù)等等,因此真實世界中的函 數(shù)式編程往往都會考慮如何將有副作用的代碼分離出來。函數(shù)式編程默認(rèn)是不 可變的,開發(fā)人員必須做些額外的事情才能使用可變狀態(tài)或是危險的副作用, 與之相反,如C獻(xiàn)Java必須使用readonly或是final來做到這一點。此時, 使

18、用函數(shù)式編程語言時的思維觀念便會有所不同了。F#是微軟隨VS 2010推出的一門函數(shù)式編程語言,它基于 OCaml的核心部 分,因此是一門強類型編程語言,并支持一些如模式匹配,類型推斷等現(xiàn)代函 數(shù)式編程語言的特性。在此之上,F(xiàn)#又增加了異步工作流,度量單位等較為前 沿的語言功能。在F#中如果要計算一個列表所有元素之和,也可以使用命令式 的風(fēng)格來編寫代碼:prelet sumSquaresI l=let mutable acc=0 for xin Ido acc-acc+sqr xacc/preacc 只不過,F(xiàn)#中的一切默認(rèn)都是不可變的,開發(fā)人員需要使用 mutable關(guān)鍵字來聲明一個可變的狀

19、態(tài)。事實上,在F#中更典型做法是:prelet rec sumSquaresF l=match lwith|-0|head : tail-sqr head+sumSquaresF tail/pre在數(shù)學(xué)里我們經(jīng)常使用遞歸,把一個公式分解成幾個變化的形式,以此進(jìn)行遞歸的定義。純函數(shù)式的代碼其"數(shù)學(xué)性"較強,如果您分析上面這段代碼,會發(fā)現(xiàn)它幾乎就是標(biāo)準(zhǔn)的數(shù)學(xué)定義。在編程時我們也 使用遞歸的做法,編譯器會設(shè)法幫我們轉(zhuǎn)化成尾調(diào)用或是循環(huán)語句。動態(tài)語言與兀編程動態(tài)語言不會嚴(yán)格區(qū)分"編譯時"和"運行時”。對于一些靜態(tài)編程語言(如 C#),往往是先進(jìn)行編譯,

20、此時可能會得到一些編譯期錯誤,而對于動態(tài)語言來 說這兩個階段便混合在一起了。常見的動態(tài)語言有JavaScript , Python, Ruby,LISP等等。動態(tài)語言和靜態(tài)語言各有一些優(yōu)勢,這也是兩個陣營爭論多年的內(nèi) 容。不過Anders認(rèn)為它們各自都有十分重要的優(yōu)點,而未來不屬于其中任何一 方。他表示,從編程語言發(fā)展過程中可以觀察到兩種特點正在合并的趨勢,未 來應(yīng)該屬于兩者的雜交產(chǎn)物。許多人認(rèn)定動態(tài)語言執(zhí)行起來很慢,也沒有類型安全等等。例如有這樣一 段代碼:prevar a=0,n=10 ; for(var i=0; i n ; i+)a+=i ; /pre這段代碼在 C#ffiJavaSc

21、ript中都是合法的,但是它們的處理方式大相徑庭。在C#,編譯器可以推斷出a和n都是32位整數(shù),則for循環(huán)和相加操作都只是簡單的 CPU旨令, 自然效率很高。但是對于JavaScript等動態(tài)類型語言來說,var只代表了 "一 個值",它可以是任意類型,因此這里其實還會包含一個“類型標(biāo)記",表明它在運行時是什么類型的對象。所以兩者的區(qū)別之一便是,表示同樣的值在動態(tài)語 言中會有一些額外的開銷,在如今的 CPlfr,"空間"也意味著"速度",所以較大的值便需要較長時間進(jìn)行處理,這里便損失了一部分效率。此外 JavaScript

22、 在計算a力口 i時,那么必須先查看兩個變量中的類型標(biāo)記,根據(jù)類型選擇出合 適的相加操作,然后加載兩個值,最后再進(jìn)行加法操作,一旦越界了還要利用 double。很明顯在這里也會帶來許多開銷。一般來說,動態(tài)語言是使用解釋器 來執(zhí)行的,因此還有一些解釋器需要的二進(jìn)制碼,把這些性能損失全部加起來 以后,便會發(fā)現(xiàn)執(zhí)行代碼時需要10倍到100倍的性能開銷。不過近幾年出現(xiàn)的一些動態(tài)虛擬機(jī)或引擎將此類情況改善了許多。如今大 部分的JavaScript引擎使用了 JIT編譯器,于是使省下了解釋器的開銷,這樣 性能損失便會減小至3到10倍。而在過去的兩三年間,JIT編譯器也變得越來 越高效,瀏覽器中新一代的適應(yīng)

23、性 JIT編譯器,如TraceMonkey, V8,還有微 軟在IE 9中使用的Chakra引擎。這種適應(yīng)性的JIT編譯器使用了一部分有趣 的技術(shù),如 Inline Caching 、 Type Specialization 、 Hidden Classes 、 Tracing等等,它們可以將開銷降低至 2到3倍的范圍內(nèi),這種效率的提升可 謂十分神奇。在Anders看來,JavaScript引擎可能已經(jīng)接近了性能優(yōu)化的極 限,我們在效率上可以提升的空間已經(jīng)不多。不過他同樣認(rèn)為,如今JavaScript語言的性能已經(jīng)足夠快了,完全有能力作為亞烷戶端的統(tǒng)治性語 言。動態(tài)語言的關(guān)鍵之一便是"

24、;元編程","元編程"實際上是"代碼生成"的一種 別稱,在日常應(yīng)用中開發(fā)人員其實經(jīng)常依賴這種做法了。在某些場景下使用動 態(tài)語言會比靜態(tài)語言更加自然一些。例如在C臧Java里使用ORMf, 一種傳統(tǒng)做法是讓代碼生成器去觀察數(shù)據(jù)庫,并生成一大堆代碼,然后再編譯。而動 態(tài)語言并沒有編譯期和執(zhí)行期的區(qū)別,例如在Ruby on Rails中使用ActiveRecord便無須定義各式字段。Anders談到,他和他的團(tuán)隊也在努力改進(jìn)靜態(tài)語言的元編程能力,如他們 正在實現(xiàn)的"編譯器即服務(wù)(Compiler as aService)"。傳統(tǒng)的

25、編譯器是一個黑 盒,一端輸入代碼,而另一端便會生成.NET程序集等數(shù)據(jù),開發(fā)人員很難參與 或理解它的工作。但是在很多時候,開發(fā)人員并不一定需要編譯器來生成程序 集,他們需要的是一些樹狀的表現(xiàn)形式,然后對它進(jìn)行識別和重寫。因此,開 發(fā)人員可能會越來越需要一些開放編譯器功能的API。這么做可以讓靜態(tài)類型語言獲得許多有用的功能,包括元編程以及可操作的完整對象模型等等。并發(fā)Anders看來,多核革命的一個有趣之處在于,它會要求并發(fā)的思維方式有 所改變。傳統(tǒng)的并發(fā)思維,是在單個 CPU1執(zhí)行多個邏輯任務(wù),使用舊有的分 時方式或是時間片模型來執(zhí)行多個任務(wù)。但是如今的并發(fā)場景則正好相反,是 要將一個邏輯上的

26、任務(wù)放在多個 CPU1執(zhí)行。這改變了我們編寫程序的方式, 這意味著對于語言或是API來說,我們需要有辦法來分解任務(wù),把它拆分成多 個小任務(wù)后獨立的執(zhí)行,而傳統(tǒng)的編程語言中并不關(guān)注這點。使用目前的并發(fā)API來完成工作并不容易,比如 Thread, ThreadPool , Monitor等等,開發(fā)人員很難走的太遠(yuǎn)。不過在.NET 4.0中提供了一套強大的 框架,即.NET并行擴(kuò)展(Parallel Extensions) ,這是一種現(xiàn)代的并發(fā)模型, 將邏輯上的任務(wù)并發(fā)與實際使用的的物理模型分離開來。以前的 API都是直接 處理線程等基礎(chǔ)元素,不過利用.NET并行擴(kuò)展中的任務(wù)并行庫(Task Pa

27、rallel Library),并行 LINQ(Parallel LINQ) 以及協(xié)調(diào)數(shù)據(jù)結(jié)構(gòu)(Coordination Data Structures)讓開發(fā)人員可以直接關(guān)注邏輯上的任務(wù),而不必關(guān)心它們是如何運 行的,或是使用了多少個線程和 CPU?等。利用LINQ這樣的DSL也有助于寫出 并行的代碼,如果使用普通的for循環(huán)配合線程池來實現(xiàn)并行,則開發(fā)人員很 容易在各種API里失去方向。不過事實上,編寫并行的代碼依然很困難,尤其是要識別出可以并行的地 方。Anders認(rèn)為很多時候還是需要編程語言來關(guān)注這方面的事情(如下圖)。比如"隔離性(Isolation)”,即編譯器如何發(fā)現(xiàn)這段代碼是獨立的,便可

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論