本文主要是關(guān)于計算機編程語言的相關(guān)介紹,并著重對計算機編程語言的發(fā)展趨勢進行了詳盡的分析。
計算機編程語言
計算機語言包括機器語言、匯編語言、高級語言。機器語言是用二進制代碼表示的計算機能直接識別和執(zhí)行的一種機器指令的集合。它是計算機的設(shè)計者通過計算機的硬件結(jié)構(gòu)賦予計算機的操作功能,比如匯編語言(assembly language)。機器語言具有靈活、直接執(zhí)行和速度快等特點。高級語言比較容易識記和理解,像C B語言等。
語言匯總
工業(yè)編程語言:A+ | Ada | 匯編語言| B |Brain***| C | C++ |C++/CLI| Cg | COBOL | Eiffel | Erlang | FORTRAN | IronPython | Java | JRuby | Jython | LISP | Oberon |Objective-C|Ocaml| Pascal | Perl | Powerbuilder | Python | QBASIC | R | REXX | Ruby | Self | Smalltalk | SQL | Tcl/Tk | Visual Basic | PHP | C# | F# | J# |Visual Basic .NET|易語言
腳本編程語言:ActionScript | JavaScript | JScript |Nuva| PostScript | VBScript | lua
學(xué)術(shù)編程語言:APL/J | Haskell | Logo | ML |pascal|Prolog | Scheme | SAC
其他編程語言:ALGOL | BASIC| Clipper | Forth | Modula-2/Modula-3 | MUMPS | PL/I | Simula
語言發(fā)展
計算機主要是由兩大部分構(gòu)成的,硬件和軟件,硬件就不用解釋了,你的主機、顯示器等等都屬于硬件,但是光有硬件電腦是沒有辦法使用的,除非你拿機箱當(dāng)柜子用!呵呵!所以就必須有軟件支持!軟件又分為系統(tǒng)軟件,也就是你經(jīng)常用的操作系統(tǒng),WIN XP,Win 2000等等!再就是通用軟件和應(yīng)用軟件。計算機語言也有一個發(fā)展過程,從最開始的計算機語言,也就是011010111,那個時候編程恐怕是非常痛苦的事,因為你要會用0和1表示一切!后來逐步發(fā)展,把一些常用的指令用英語單詞表示出來,形成了匯編語言,這個時候也是比較痛苦的,你要記住那些單詞的含義不說,還必須告訴計算機每一步要怎么做,而計算機又是一個非常笨的東西,你掉一個步驟他就罷工!而且匯編語言的可移植性差,也就是說你在這臺電腦上寫的程序到另一臺電腦上可能就不能用了。之后為了方便軟件移植,高級語言誕生了,高級語言不要求程序員掌握計算機的硬件運行,只要寫好上層代碼,編譯軟件會將高級語言翻譯成匯編語言,然后再將匯編語言轉(zhuǎn)化成計算機語言,從而在計算機中執(zhí)行。因此,程序員使用高級語言寫得代碼可以移植到其他計算機執(zhí)行,而不用考慮計算機硬件的特性。
語言使用方向
想設(shè)計一款美觀的Web應(yīng)用
JavaScript可使網(wǎng)站看起來更棒,同時存在大量可兼容的框架,如Ember、Angular、Backbone等,它們都可以幫你組織、構(gòu)造兼容不同瀏覽器的Web應(yīng)用。目前,JavaScript正逐步成為主要的企業(yè)級編程語言。
JavaScript可在幾乎所有的瀏覽器上運行,可同時用來編寫前端與后端服務(wù)。無論你開發(fā)什么應(yīng)用,JavaScript是必須的語言,而你也不用考慮應(yīng)用采用的是何種后端技術(shù)。
需要快速開發(fā)原型
如果你是設(shè)計師,想學(xué)習(xí)后端編程技術(shù)以測試應(yīng)用,那Ruby和Python將是不錯的選擇。這兩門語言已入選2013年最流行工作技巧Top 5。
學(xué)習(xí)Python,可以利用Learn Python The Hard Way網(wǎng)站上的資源,學(xué)習(xí)Ruby,可以登陸Codecademy中的Ruby子欄目。
想構(gòu)建一個Android應(yīng)用
開發(fā)Android應(yīng)用,最多使用Java語言。
你可以在Windows和Mac上開發(fā)Android應(yīng)用,之后購買廉價的設(shè)備來測試你的應(yīng)用。隨著Andriod正逐漸占領(lǐng)移動市場,越來越多的開發(fā)者正選擇從Android開始入手。
Udacity上免費的JavaScript編程課程很適合初學(xué)者。一旦你掌握到Java,就可以登錄官方Android開發(fā)者網(wǎng)站,學(xué)習(xí)如何創(chuàng)建第一個Android項目。
想開發(fā)一款iOS應(yīng)用
在Mac上,你可以使用Objective-C開發(fā)可運行于iPhone、iPad、iPod上的iOS應(yīng)用。與Android相比,iOS的碎片化程序更低,開發(fā)者很容易創(chuàng)建通用的應(yīng)用。
除了Object-C,開發(fā)iOS應(yīng)用還需要免費工具Xcode和iOS軟件開發(fā)工具包。你可以用Apple提供的開發(fā)者教程,或登錄到Code School網(wǎng)站中的iOS子頻道學(xué)習(xí)iOS開發(fā)。
計算機編程語言的發(fā)展趨勢分析
程序設(shè)計離不開編程語言,但是編程語言在國內(nèi)的大環(huán)境中似乎一直是個二等公民。國內(nèi)的計算機教育和工程培訓(xùn),似乎一直在宣傳“語言不重要,重要的是思想”,“語言一通百通”等觀點,甚至在許多人眼中“語言的討論”完全是不入流的,但其實“編程語言”與“工具”、“框架”或是“開發(fā)方法”等事物一樣,都對生產(chǎn)力有著重要的影響。事實上,語言的發(fā)展歷史比其他方面更為悠久,并且在過去十幾年,甚至最近幾年中都依然在不斷的碰撞,演變。期間一些新的語言誕生了,而另一些在當(dāng)時看來陽春白雪的語言和編程范式也重新獲得了人們的重視。
Anders Hejlsberg是微軟的Technical Fellow,擔(dān)任C#編程語言的首席架構(gòu)師,也參與了.NET Framework,以及VB.NET和F#等語言的設(shè)計與開發(fā)。幾個月前,Anders在比利時的TechDays 2010及荷蘭DevDays 2010分別進行了一場演講,闡述了他眼中對于編程語言的發(fā)展趨勢及未來方向,本文便對他的觀點進行了總結(jié)。
大約25到30年前,Anders開發(fā)了著名的Turbo Pascal,這是一套集語言、編譯器及開發(fā)工具于一體的產(chǎn)品,這也是Anders進入編程語言這一領(lǐng)域的起點。Anders談到,如今的計算機和當(dāng)年他開發(fā)的Turbo Pascal所用的Z-80已經(jīng)不可同日而語。從那時算起,如今的機器已經(jīng)有大約10萬倍的外部存儲容量,1萬倍的內(nèi)存大小,CPU速度也有大約1000倍的提高。但是,如果我們比較如今的Java代碼及當(dāng)年P(guān)ascal代碼,會發(fā)現(xiàn)它們的差別其實并不大。Anders認為編程語言的發(fā)展非常緩慢,期間當(dāng)然出現(xiàn)了一些東西,例如面向?qū)ο蟮鹊?,但是遠沒有好上1000倍。事實上,近幾十年來的努力主要體現(xiàn)在框架及工具等方面(如下圖)。例如.NET Framework里有超過一萬個類及十萬個方法,與Turbo Pascal相比的確有了超過1000倍的增長。同樣類似,現(xiàn)在的IDE包含了無數(shù)強大的功能,例如語法提示,重構(gòu),調(diào)試器等等。與此相比,編程語言的改進的確很不明顯。
在過去5、60年的編程歷史中,編程語言的抽象級別不斷提高,人們都在努力讓編程語言更有表現(xiàn)力,這樣我們可以用更少的代碼完成更多的工作。我們一開始使用匯編,然后使用面向過程的語言(如Pascal和C),然后是面向?qū)ο笳Z言(如C++),隨后便進入了托管時代,語言運行于受托管的執(zhí)行環(huán)境上(如C#,Java),它們的主要特性有自動的垃圾收集,類型安全等等。Anders認為這樣的趨勢還會繼續(xù)保持下去,我們還會看到抽象級別越來越高的語言,而語言的設(shè)計者則必須理解并預(yù)測下一個抽象級別是什么樣子的。另一方面,如.NET,Java等框架的重要性提高了許多,編程語言往往都傾向于構(gòu)建于現(xiàn)有的工具上,而不會從頭寫起。現(xiàn)在出現(xiàn)的編程語言,例如F#,以及Java領(lǐng)域的Scala,Clojure等等,它們都是基于現(xiàn)有框架構(gòu)建的,每次從頭開始的代價實在太高。
在Anders眼中,如今影響力較大的趨勢主要有三種(如下圖),它們分別是“聲明式的編程風(fēng)格”(包括“領(lǐng)域特定語言”及“函數(shù)式編程”)、過去的五年非?;馃岬摹皠討B(tài)語言”(其最重要的方面便是“元編程”能力)以及多核環(huán)境下的“并發(fā)編程。此外隨著語言的發(fā)展,原本常用的“面向?qū)ο蟆闭Z言,“動態(tài)語言”或是“函數(shù)式”等邊界也變得越來越模糊,例如各種主要的編程語言都受到函數(shù)式語言的影響。因此,“多范式”程序設(shè)計語言也是一個愈發(fā)明顯的趨勢。
聲明式編程與DSL
目前常見的編程語言大都是命令式(Imperative)的,例如C#,Java或是C++等等。這些語言的特征在于,代碼里不僅表現(xiàn)了“做什么(What)”,而更多表現(xiàn)出“如何(How)完成工作”這樣的實現(xiàn)細節(jié),例如for循環(huán),i += 1等等,甚至這部分細節(jié)會掩蓋了我們的“最終目標(biāo)”。在Anders看來,命令式編程通常會讓代碼變得十分冗余,更重要的是由于它提供了過于具體的指令,這樣執(zhí)行代碼的基礎(chǔ)設(shè)施(如CLR或JVM)沒有太多發(fā)揮空間,只能老老實實地根據(jù)指令一步步的向目標(biāo)前進。例如,并行執(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不是什么新鮮的玩意兒,我們平時經(jīng)常接觸的SQL,CSS,正則表達式等等都屬于DSL。有的DSL可能更加專注于一個方面,例如Mathematica,LOGO等等。這些語言的目標(biāo)都是特定的領(lǐng)域,與之相對的則是GPPL(General Purpose Programming Language,通用目的編程語言)。Martin Fowler將DSL分為外部DSL及內(nèi)部DSL兩種。外部DSL有自己的特定語法、解析器和詞法分析器等等,它們往往是一種小型的編程語言,甚至不會像GPPL那樣需要源文件。與之相對的則是內(nèi)部DSL。內(nèi)部DSL其實更像是種別稱,它代表一類特別API及使用模式。
XSLT,SQL等等都可以算作是外部DSL。外部DSL一般會直接針對特定的領(lǐng)域設(shè)計,而不考慮其他方面。James Gosling曾經(jīng)說過:每個配置文件最終都會變成一門編程語言。一開始您可能只會用它表示一點點東西,慢慢地您便會想要一些規(guī)則,而這些規(guī)則則變成了表達式,后來您可能還會定義變量,進行條件判斷等等,而最終它就變成了一種奇怪的編程語言,這樣的情況屢見不鮮?,F(xiàn)在有一些公司也在關(guān)注DSL的開發(fā)。例如以前在微軟工作的Charles Simonyi提出了Intentional Programming的概念,還有JetBrains公司提供的一個叫做MPS(Meta Programming System)的產(chǎn)品。最近微軟也提出了自己的Oslo項目,而在Eclipse世界里也有Xtext,所以其實如今在這方面也有不少人在嘗試。由于外部DSL的獨立性,在某些情況下也會出現(xiàn)特定的工具,輔助領(lǐng)域?qū)<一蚴情_發(fā)人員本身編寫DSL代碼。還有一些DSL會以XML方言的形式提出,利用XML方言的好處在于有不少現(xiàn)成的工具可用,這樣可以更快地定義自己的語法。
而內(nèi)部DSL,正像之前提到的那樣,它往往只是代表了一系列特別的API及使用模式,例如LINQ查詢語句及Ruby on Rails中的Active Record聲明代碼等等。內(nèi)部DSL可以使用一系列API來“偽裝”成一種DSL,它往往會利用一些“流暢化”的技巧,例如像jQuery那樣把一些方法通過“點”連接起來,而另一些也會利用元編程的方式。內(nèi)部DSL還有一些優(yōu)勢,例如可以訪問語言中的代碼或變量,以及利用代碼補全,重構(gòu)等母語言的所有特性。
DSL的可讀性往往很高。例如,要篩選出單價大于20的產(chǎn)品,并對所屬種類進行分組,并降序地列出每組的分類名稱及產(chǎn)品數(shù)量。如果是用命令式的編程方式,則可能是這樣的:
Dictionary《string, Grouping》 groups = new Dictionary《string, Grouping》();
foreach (Product p in products)
{
if (p.UnitPrice 》= 20)
{
if (!groups.ContainsKey(p.CategoryName))
{
Grouping r = new Grouping();
r.CategoryName = p.CategoryName;
r.ProductCount = 0;
groups[p.CategoryName] = r;
}
groups[p.CategoryName].ProductCount++;
}
}
List《Grouping》 result = new List《Grouping》(groups.Values);
result.Sort(delegate(Grouping x, Grouping y)
{
return
x.ProductCount 》 y.ProductCount ? -1 :
x.ProductCount 《 y.ProductCount ? 1 :
0;
});
顯然這些代碼編寫起來需要一點時間,且很難直接看出它的真實目的,換言之“What”幾乎完全被“How”所代替了。這樣,一個新的程序員必須花費一定時間才能理解這段代碼的目的。但如果使用LINQ,代碼便可以改寫成:
var result = products
.Where(p =》 p.UnitPrice 》= 20)
.GroupBy(p =》 p.CategoryName)
.OrderByDescending(g =》 g.Count())
.Select(g =》 new { CategoryName = g.Key, ProductCount = g.Count() });
這段代碼更加關(guān)注的是“What”而不是“How”,它不會明確地給出過濾的“操作方式”,也沒有涉及到創(chuàng)建字典這樣的細節(jié)。這段代碼還可以利用C# 3.0中內(nèi)置的DSL,即LINQ查詢語句來改寫:
var result =
from p in products
where p.UnitPrice 》= 20
group p by p.CategoryName into g
orderby g.Count() descending
select new { CategoryName = g.Key, ProductCount = g.Count() };
編譯器會簡單地將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年前許多人開始吸收和整理這些研究內(nèi)容,想要把它們?nèi)谌敫鼮橥ㄓ玫木幊陶Z言?,F(xiàn)在的編程語言,如C#、Python、Ruby、Scala等等,它們都受到了函數(shù)式編程語言的影響。
使用命令式編程語言寫程序時,我們經(jīng)常會編寫如x = x + 1這樣的語句,此時我們大量依賴的是可變狀態(tài),或者說是“變量”,它們的值可以隨程序運行而改變??勺儬顟B(tài)非常強大,但隨之而來的便是被稱為“副作用”的問題,例如一個無需參數(shù)的void方法,它會根據(jù)調(diào)用次數(shù)或是在哪個線程上進行調(diào)用對程序產(chǎn)生影響,它會改變程序內(nèi)部的狀態(tài),從而影響之后的運行效果。而在函數(shù)式編程中則不會出現(xiàn)這個情況,因為所有的狀態(tài)都是不可變的。事實上對函數(shù)式編程的討論更像是數(shù)學(xué)、公式,而不是程序語句,如x = x + 1對于數(shù)學(xué)家來說,似乎只是個永不為真的表達式而已。
函數(shù)式編程十分容易并行,因為它在運行時不會修改任何狀態(tài),因此無論多少線程在運行時都可以觀察到正確的結(jié)果。假如兩個函數(shù)完全無關(guān),那么它們是并行還是順序地執(zhí)行便沒有什么區(qū)別了。當(dāng)然,現(xiàn)實中的程序一定是有副作用的,例如向屏幕輸出內(nèi)容,向Socket傳輸數(shù)據(jù)等等,因此真實世界中的函數(shù)式編程往往都會考慮如何將有副作用的代碼分離出來。函數(shù)式編程默認是不可變的,開發(fā)人員必須做些額外的事情才能使用可變狀態(tài)或是危險的副作用,與之相反,如C#或Java必須使用readonly或是final來做到這一點。此時,使用函數(shù)式編程語言時的思維觀念便會有所不同了。
F#是微軟隨VS 2010推出的一門函數(shù)式編程語言,它基于OCaml的核心部分,因此是一門強類型編程語言,并支持一些如模式匹配,類型推斷等現(xiàn)代函數(shù)式編程語言的特性。在此之上,F(xiàn)#又增加了異步工作流,度量單位等較為前沿的語言功能。在F#中如果要計算一個列表所有元素之和,也可以使用命令式的風(fēng)格來編寫代碼:
let sumSquaresI l =
let mutable acc = 0
for x in l do
acc 《- acc + sqr x
acc
acc只不過,F(xiàn)#中的一切默認都是不可變的,開發(fā)人員需要使用mutable關(guān)鍵字來聲明一個可變的狀態(tài)。事實上,在F#中更典型做法是:
let rec sumSquaresF l =
match l with
| [] -》 0
| head :: tail -》 sqr head + sumSquaresF tail
在數(shù)學(xué)里我們經(jīng)常使用遞歸,把一個公式分解成幾個變化的形式,以此進行遞歸的定義。純函數(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#),往往是先進行編譯,此時可能會得到一些編譯期錯誤,而對于動態(tài)語言來說這兩個階段便混合在一起了。常見的動態(tài)語言有JavaScript,Python,Ruby,LISP等等。動態(tài)語言和靜態(tài)語言各有一些優(yōu)勢,這也是兩個陣營爭論多年的內(nèi)容。不過Anders認為它們各自都有十分重要的優(yōu)點,而未來不屬于其中任何一方。他表示,從編程語言發(fā)展過程中可以觀察到兩種特點正在合并的趨勢,未來應(yīng)該屬于兩者的雜交產(chǎn)物。
許多人認定動態(tài)語言執(zhí)行起來很慢,也沒有類型安全等等。例如有這樣一段代碼:
var a = 0, n = 10;
for (var i = 0; i 《 n; i++) {
a += i;
}
這段代碼在C#和JavaScript中都是合法的,但是它們的處理方式大相徑庭。在C#中,編譯器可以推斷出a和n都是32位整數(shù),則for循環(huán)和相加操作都只是簡單的CPU指令,自然效率很高。但是對于JavaScript等動態(tài)類型語言來說,var只代表了“一個值”,它可以是任意類型,因此這里其實還會包含一個“類型標(biāo)記”,表明它在運行時是什么類型的對象。所以兩者的區(qū)別之一便是,表示同樣的值在動態(tài)語言中會有一些額外的開銷,在如今的CPU中,“空間”也意味著“速度”,所以較大的值便需要較長時間進行處理,這里便損失了一部分效率。此外JavaScript在計算a加i時,那么必須先查看兩個變量中的類型標(biāo)記,根據(jù)類型選擇出合適的相加操作,然后加載兩個值,最后再進行加法操作,一旦越界了還要利用double。很明顯在這里也會帶來許多開銷。一般來說,動態(tài)語言是使用解釋器來執(zhí)行的,因此還有一些解釋器需要的二進制碼,把這些性能損失全部加起來以后,便會發(fā)現(xiàn)執(zhí)行代碼時需要10倍到100倍的性能開銷。
不過近幾年出現(xiàn)的一些動態(tài)虛擬機或引擎將此類情況改善了許多。如今大部分的JavaScript引擎使用了JIT編譯器,于是便省下了解釋器的開銷,這樣性能損失便會減小至3到10倍。而在過去的兩三年間,JIT編譯器也變得越來越高效,瀏覽器中新一代的適應(yīng)性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)不多。不過他同樣認為,如今JavaScript語言的性能已經(jīng)足夠快了,完全有能力作為Web客戶端的統(tǒng)治性語言。
動態(tài)語言的關(guān)鍵之一便是“元編程”,“元編程”實際上是“代碼生成”的一種別稱,在日常應(yīng)用中開發(fā)人員其實經(jīng)常依賴這種做法了。在某些場景下使用動態(tài)語言會比靜態(tài)語言更加自然一些。例如在C#或Java里使用ORM時,一種傳統(tǒng)做法是讓代碼生成器去觀察數(shù)據(jù)庫,并生成一大堆代碼,然后再編譯。而動態(tài)語言并沒有編譯期和執(zhí)行期的區(qū)別,例如在Ruby on Rails中使用ActiveRecord便無須定義各式字段。
Anders談到,他和他的團隊也在努力改進靜態(tài)語言的元編程能力,如他們正在實現(xiàn)的“編譯器即服務(wù)(Compiler as a Service)”。傳統(tǒng)的編譯器是一個黑盒,一端輸入代碼,而另一端便會生成.NET程序集等數(shù)據(jù),開發(fā)人員很難參與或理解它的工作。但是在很多時候,開發(fā)人員并不一定需要編譯器來生成程序集,他們需要的是一些樹狀的表現(xiàn)形式,然后對它進行識別和重寫。因此,開發(fā)人員可能會越來越需要一些開放編譯器功能的API。這么做可以讓靜態(tài)類型語言獲得許多有用的功能,包括元編程以及可操作的完整對象模型等等。
并發(fā)
Anders看來,多核革命的一個有趣之處在于,它會要求并發(fā)的思維方式有所改變。傳統(tǒng)的并發(fā)思維,是在單個CPU上執(zhí)行多個邏輯任務(wù),使用舊有的分時方式或是時間片模型來執(zhí)行多個任務(wù)。但是如今的并發(fā)場景則正好相反,是要將一個邏輯上的任務(wù)放在多個CPU上執(zhí)行。這改變了我們編寫程序的方式,這意味著對于語言或是API來說,我們需要有辦法來分解任務(wù),把它拆分成多個小任務(wù)后獨立的執(zhí)行,而傳統(tǒng)的編程語言中并不關(guān)注這點。
使用目前的并發(fā)API來完成工作并不容易,比如Thread,ThreadPool,Monitor等等,開發(fā)人員很難走的太遠。不過在.NET 4.0中提供了一套強大的框架,即.NET并行擴展(Parallel Extensions),這是一種現(xiàn)代的并發(fā)模型,將邏輯上的任務(wù)并發(fā)與實際使用的的物理模型分離開來。以前的API都是直接處理線程等基礎(chǔ)元素,不過利用.NET并行擴展中的任務(wù)并行庫(Task Parallel 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認為很多時候還是需要編程語言來關(guān)注這方面的事情(如下圖)。比如“隔離性(Isolation)”,即編譯器如何發(fā)現(xiàn)這段代碼是獨立的,便可以將其安全地并發(fā)執(zhí)行。某段代碼創(chuàng)建了一個對象,在分享給其他人之前,我們對它的改變是安全的,但是一旦將其共享出去以后便完全不同了。因此理想中的類型系統(tǒng)應(yīng)該可以跟蹤到這樣的共享,如Linear Types——這在學(xué)術(shù)界也有一些研究。編程語言也可以在函數(shù)的純潔性(Purity)方面下功夫,如關(guān)注某個函數(shù)是否有副作用,有些時候編譯器可以做這方面的檢查,它可以禁止某些操作,以此保證我們寫出無副作用的純函數(shù)。另外便是不可變性(Immutability),目前的語言,如C#或VB,我們需要額外的工作才能寫出不可變的代碼。Anders認為合適的做法應(yīng)該是在語言層面上更好的支持不可變性。這些都是在并發(fā)方面需要考慮的問題。
Anders還提到了他在思考并發(fā)語言特性時所遵循的原則:一個語言特性不應(yīng)該針對某個特定的并發(fā)模型,而應(yīng)該是一種通用的,可用于各種不同的并發(fā)場景的特性,就像隔離性、純潔性及不可變性那樣。語言擁有這樣的特性之后,就可以用于構(gòu)建各種不同的API,各種并發(fā)方式都可以利用到核心的語言特性。
總結(jié)
Anders認為,對于編程語言來說,現(xiàn)在出現(xiàn)了許多有趣的東西,也是個令人激動的時刻。在過去,大約是1995到2005年,的確可以說是一個編程語言的黃金時期。當(dāng)Java出現(xiàn)的時候,編程語言的門檻變得平坦了,一切都是Java,似乎其他編程語言都完蛋了,程序設(shè)計者也沒什么可做的。不過大家又逐漸發(fā)現(xiàn),其實這遠沒有結(jié)束。現(xiàn)在回顧起來,會發(fā)現(xiàn)這段時間又出現(xiàn)了許多有趣的編程語言,這其實也代表了我們在編程領(lǐng)域上的進步。
計算機編程語言的幾個發(fā)展階段及特點
一、面向機器的語言
最開始的時候,每種計算機都有自己的機器指令。例如,某種型號的計算機用8位二進制信息10001010表示加法指令,等等。所以用這種機器語言進行程序設(shè)計是很累的工作,而且代碼難以閱讀和理解,還有就是可能同樣的任務(wù),不同的計算機之間指令有所不同。后來用一些簡單的符號來代替二進制指令,但匯編語言仍是面向機器的語言,需針對不同的機器來編寫不同的代碼。習(xí)慣上稱機器語言、匯編語言為低級語言。
二、面向過程語言
20世紀(jì)60年代出現(xiàn)了過程設(shè)計語言,如c語言等。語言把代碼組成叫做過程或函數(shù)的塊,每個塊的目標(biāo)是完成某個任務(wù)。這樣的語言的好處是,不必再去考慮機器指令的細節(jié),過程語言的語法更接近人們的自然語言,人們只需按照自己的意圖來編寫各個函數(shù),而習(xí)慣上稱過程語言為高級語言。
三、面向?qū)ο笳Z言
對于許多應(yīng)用型問題,人們希望寫出易維護、易拓展、易復(fù)用的程序代碼。過程語言只有解決問題的過程(方法),而沒有指明對象。那么因此面對對象語言的一個簡單理念就是:需完成某種任務(wù)時,首先想到,誰去完成任務(wù),即那個對象去完成任務(wù);提到數(shù)據(jù),首先想到這個數(shù)據(jù)是哪個對象的。
在我眼里,基于對象的編程語言,優(yōu)點不僅如上所講,更重要的是它鼓勵創(chuàng)造性的設(shè)計。
面向?qū)ο缶幊讨饕w現(xiàn)三個特征:封裝性、繼承、多態(tài)。
結(jié)語
關(guān)于計算機編程語言的相關(guān)介紹就到這了,如有不足之處歡迎指正。
評論