程式設計語言簡史
轉載:原文連結Here
一個朋友在跟我一塊吃午飯的時候問了我一個問題:現代程式設計語言的發展曆程是什麼樣的,它是如何發展到現在這樣的?
他覺得我應該能答得上來,但其實我隻能說個大概。
我跟他提了下機器語言,以及人們為了簡化它所做的努力,并逐漸發明了一些更抽象的語言,它們最終會被翻譯成0和1。
但是:一個偶然的機會我看到了Crockford關于Javascript的一個分享,開篇的時候他講的正是程式設計語言的發展史——盡管這主要
是關于JavaScript以及影響到它的那些語言——這比我講的可要生動多了。
------
穿孔卡
一些都得從穿孔卡開始說起——就是一張張打滿了小洞的紙片(下面有圖有真相)。
發明
美國憲法中要求,每10年就得進行一次人口普查。到了19世紀末期,人口增長的實在是太頻繁了,以至于1880的人口普查曆時8年才最終完成,當時還都是通過紙和筆來完成的。
1890年,Herman Hollerith被授命去解決這一問題,他最終使用了穿孔卡來存儲資料,并用一台制表機(tabulating machine)來進行統計和排序。
資料是根據硬紙片上打孔的位置來進行編碼的,排列的方式是我們現在所熟識的行列式,并可以通過機器來進行處理。
這次人口普查隻花了一年時間便完成了。
IBM
1896年,Hollerith成立了制表機器公司,開始了自己的事業。他把自己的裝置和卡片出售給大的保險公司,以及包括英國,意大利,德國,俄羅斯,澳洲,加拿大,法國,挪威,波多黎各,菲律賓等國在内的多國政府
參見Here。
他的公司後來跟别的公司進行了合并,并在1924年最終成為了國際商業機器公司。沒錯,它就是IBM。
現代用途
穿孔卡被認為是将資料錄入到機器的最便捷的一種方式。
IBM後來仍然在使用這套系統——它叫做機關記錄管理(Unit Record Management)——并一直用到了70年代,當然了,這比Hollerith最初的設計要先進得多。
Hollerith的穿孔卡流傳甚廣。它很快便被改進成了更簡單的行列組。
80個字元的限制
确切來說是12行,80列。你可能看到過有80個字元這個限制,是的,這是因為一張卡片最大的字元數就是80個。
沒錯,這已經被淘汰了好幾十年了,不過80個字元的這個限制仍然延用到了現在。
這個卡片可以用來做許多事情。比如說,顧客不會直接收到帳單而是收到了一些卡片,他們将卡片仔細地打上孔後再和要付的款項一同返還給商家。公司收到這些後會再進行處理并确認這次交易。
記賬機是可程式設計的,它應該可以算作是世界上第一台現代的計算機。
大型機/分時時代
大型機是政府與企業用來運作關鍵任務的大型計算機。
在PC機發明以前(50年代到70年代),人們能使用的計算機就隻有大型機。
大型機非常昂貴且體型巨大,隻有大型的企業以及一些大學才有。幾乎每台機器都是獨一無二的,跟别的大型機完全不同。一套完整的系統由多個單元組成,占的地方有一整間屋子那麼大。
大型機将程式和資料存儲在記憶體中。你得使用最原始的指令來編寫程式。
還是穿孔卡
我為什麼一開始就講到穿孔卡是有我的原因的:-)
你得将指令在一堆卡片上進行穿孔才能運作你的程式。作為程式員,你是沒有自己的計算機的,你得将程式寫在這些穿孔卡上(或者是紙上,當然得有人把它們轉換成穿孔卡),然後把這些卡片交給一個操作員,他會負責把它們錄入到大學或者公司的機器裡。過幾個小時你就可以回來了,操作員會把結果列印出來給你,當然了,也會把你的卡片還給你。
如果你漏掉了一個分号的話,你得先修複這個問題,然後等第二天再來。
幸運的是當這些都還是常态的時候我還沒出生,不過我也明白了當一個程式員是得有多苦逼。
分時系統
由于計算機的時間非常寶貴,這段時期分時系統是最常見的操作計算機的方式。
這意味着不同的人可以通過一個終端來接入到同一台大型機上去使用它的資源。你可以使用打字機進行程式設計,完成之後再把你的程式送出上來。
打字機非常慢,一秒隻能列印10個字元。這意味着你對程式的輸出得計算得非常精确。
隻有當你送出了自己的作業時計算機才會執行你的程式,其它時間你都處于離線狀态(未連接配接到大型機上)。
分時技術在60年代就已經出現了,直到70年代末期這仍是當時主流的程式設計方式。
ASCII
說到字元集,當時隻支援非常有限的一些字元——不支援重音字母(accented letter),是以隻适合使用英語。
為什麼錯誤又被稱為BUG?
1889年,托馬斯.愛迪生連續兩天晚上都在折騰他的留聲機,因為它突然就沒法用了,還會發出蟋蟀或者臭蟲(BUG)的聲音。于是便有了關于這個瘋狂的發明家的一個笑話,就是說如果他能把自己發明裡的臭蟲清理掉的話,就可以變得很有錢,這也是第一次有記載的使用BUG來命名缺陷的記錄。
第二次世界大戰中,Grace Hopper發現一台電腦無法工作了,後來發現是因為一個繼電器裡面有隻飛蛾,她把這事給記錄了下來,"這是第一個發現的真正的BUG"。
創新之源(mother of all demos)
1968年,Doug Engelbart展示了如下幾樣東西:
滑鼠
超文本
螢幕顯示
元件
視訊會議
待辦事項
這些想法并沒有讓他變得富有也沒有立馬流行起來。不過它們為Xerox PARC所做的研究奠定了基礎,于是誕生了第一個GUI系統,随後它便被Apple Lisa,Macintosh,微軟所采用并逐漸流行了起來。
迷你/微型計算機
繼大型機之後,微機開始登上了舞台。
最終微型計算機成為了主流。微機就是非常小型的終端也稱為個人計算機(PC,盡管當時幾乎還沒人在用)。
我認為,70年代才開始有了真正的計算機。
微軟
這應該是家喻戶曉的了——微軟最早以Altair 8800起家的——這是一台DIY的計算機——它上面支援程式設計語言,這對位于阿爾伯克基的MITS公司(微儀系統家用電子公司)而言多少顯得有點價值。"Microsoft"的真正意思是“微型計算機軟體”
好吧,看起來程式員這行一開始并不好混啊。
不同的計算機工作的方式各不相同,不過相同的一點是它們都隻認二進制代碼。也就是說,0和1的序列。計算機采用這種方式是因為這和電子開關非常契合,關就是0,開就是1。計算機其實還挺笨的。
剛開始的時候,要想在計算機上程式設計你得能夠了解它的語言。也就是說,你得用0和1來和它交流。很明顯對人類而言這絕對是噩夢,計算機科學家花費了許多工夫來将它抽象得更簡單一些,以友善大家來編寫程式。
下面簡略地介紹了一下一些語言的來龍去脈。
機器代碼
機器代碼或者說機器語言就是計算機的CPU能直接執行的一系列指令。
每條指令都會執行一個特定的底層的任務。CPU所直接運作的程式就是由一系列這種指令所組成的。
數值型機器代碼(不是彙編代碼)可以看作是編譯及彙編後的計算機程式的最底層的一種表示形式,也可以看作是一門原始的硬體相關的程式設計語言。
直接使用數值機器代碼來程式設計程式當然也是可以的,不過你得一個個比特來維護并且要手動來計算數字位址和常量,這太枯燥了,并且非常容易出錯。現在已經沒人這麼幹了,除非是需要進行極端優化或者調試的時候。
參考彙編語言
彙編語言并不是機器代碼,不過也差不多。它直接關系到底層的架構,是以也就是沒有任何抽象。
可以通過彙程式設計式來将彙編語言翻譯成機器代碼。彙程式設計式是第一個發明出來的軟體工具。
下面是一段代碼:
MOV AL, 1h ; Load AL with immediate value 1
MOV CL, 2h ; Load CL with immediate value 2
MOV DL, 3h ; Load DL with immediate value 3
彙程式設計式早在50年代就已經出現了,因為它們并不需要太多的代碼分析:大多數時候它們隻是把指令翻譯成對應的可執行的指令就好了。程式員需要像底層的機器或者架構一樣來進行思考。
一些資源有限的電子裝置仍然在使用彙編語言,由彙編語言的程式去加載進階語言以及相關的庫(比如說,硬體固件)。
70年代和80年代間彙編語言非常流行。比如說,幾乎所有的控制台遊戲都使用彙編語言,因為可用的記憶體少到僅有幾KB。最早的1984的Macintosh機上許多代碼都是用彙編語言寫的,因為這樣比較節省資源。
Fortran
它出現的時候,人們已經對進階程式設計語言(就是比彙編語言抽象程式更高的語言)進行了大量的研究了。
Fortran最早是在50年代由IBM所發明的。
這個時候,發明特定的程式設計語言是為了解決特定領域的問題的:Fortran的發明是用于科學計算的,它很快便成為了這一領域的主流語言,并在随後的50年間取得了大量的成就。
到目前為止,在高性能計算領域它還是最流行的程式設計語言之一,世界上最快的超級計算機的測試及排名的程式就是由它編寫的(參見http://en.wikipedia.org/wiki/Fortran)。
Fortran開創了使用星号來進行乘法的慣例,現在幾乎所有的語言都仍在沿用這一規。
Fortran程式是這樣的:
Program Hello
Print *, "Hello World!"
End Program Hello
下面是一張包含了一個Fortran程式的穿孔卡:
COBOL
COBOL(COmmon Business-Oriented Language, 面向商業的通用語言)的設計目标是用于商業用途。它試圖使得程式設計語言看上去更像是英語,這樣程式設計人員和維護人員都能看得懂。
Grace Hopper 也是它的設計者之一(就是發現了“BUG”的那位女士),她還發明了一門類英語的資料處理語言FLOW-MATIC,要實作一門類英語的通用的業務開發語言,她絕對是不二人選。
下面是COBOL中一個"Hello World!"程式的例子:
IDENTIFICATION DIVISION.
PROGRAM-ID. HELLO-WORLD.
ENVIRONMENT DIVISION.
DATA DIVISION.
PROCEDURE DIVISION.
MAIN.
DISPLAY 'Hello, world.'.
STOP RUN.
BASIC
BASIC(初學者通用符号指令代碼,Beginner’s All-purpose Symbolic Instruction Code)由John G. Kemeny與Thomas E.Kurtz于1964年在新罕布什爾州的達特茅斯學院所發明。
BASIC就是為了分時系統所設計的。它是簡化版的Fortran,更容易進行程式設計。
它提供了一種非常聰明的按行号來編輯程式的方式,不僅編寫程式的時候會用到,像GOTO行跳轉這樣的操作也會用到。
從70年代中期到80年代,微機上通常都安裝有不同版本的BASIC,這通常都是随着機器的固件一起釋出的,這樣小企業,教授,業餘愛好者,咨詢師等都可以在他們買得起的計算機上定制軟體。
BASIC孕育了許多不同的語言,包括Visual BASIC,很長一段時間内它都是世界上最流行的程式設計語言,它是微軟從Microsoft BASIC中改進而來的。
下面是一個簡單的BASIC程式(用GW-BASIC寫的):
10 INPUT "What is your name: ", U$
20 PRINT "Hello "; U$
30 INPUT "How many stars do you want: ", N
40 S$ = ""
50 FOR I = 1 TO N
60 S$ = S$ + "*"
70 NEXT I
80 PRINT S$
90 INPUT "Do you want more stars? ", A$
100 IF LEN(A$) = 0 THEN GOTO 90
110 A$ = LEFT$(A$, 1)
120 IF A$ = "Y" OR A$ = "y" THEN GOTO 30
130 PRINT "Goodbye "; U$
140 END
ALGOL 60
ALGOL60(算法語言1960,ALGOrithmic Language 1960)是1960年在專業協會推動下所誕生的非常優秀且影響巨大的一門程式設計語言。
它從未流行過但是它引入了許多重要的概念,包括取消GOTO語句。
像BASIC這樣的語言裡會需要用到行間跳轉,這樣使得程式的可讀性很差,寫出來的程式也很容易出錯。
ALGOL 60引入了結構體與塊的概念:它使用BEGIN和END(當時還沒有花括号呢),多虧了ALGOL 60才開始有了塊的概念,而不用再使用GOTO語句了。
ALGOL的目标是通用性更強一些,以便科學計算和業務開發都能使用。
ALGOL程式是這樣的:
procedure Absmax(a) Size:(n, m) Result:(y) Subscripts:(i, k);
value n, m; array a; integer n, m, i, k; real y;
comment The absolute greatest element of the matrix a, of size n by m
is transferred to y, and the subscripts of this element to i and k;
begin integer p, q;
y := 0; i := k := 1;
for p:=1 step 1 until n do
for q:=1 step 1 until m do
if abs(a[p, q]) > y then
begin y := abs(a[p, q]);
i := p; k := q
end
end Absmax
Pascal
Pascal由Niklaus Wirth于1968到1969年間進行設計并于1970年公諸于世,它也受到了ALGOL語言的影響。
它一度非常流行,盡管最初僅是設計為一個教學工具,但很長一段時間内有不少人都用它來進行通用性的程式設計。
然而,它的子產品化有所欠缺并有一些設計上的問題,使得這門語言程式設計起來比較困難。
上段代碼吧:
while a <> b do WriteLn('Waiting');
if a > b then WriteLn('Condition met') {no semicolon allowed!}
else WriteLn('Condition not met');
for i := 1 to 10 do {no semicolon for single statements allowed!}
WriteLn('Iteration: ', i);
repeat
a := a + 1
until a = 10;
case i of
0 : Write('zero');
1 : Write('one');
2 : Write('two');
3,4,5,6,7,8,9,10: Write('?')
end;
(我仍記得14歲的時候在學校用Pascal程式設計的情形,簡直酷斃了)。
B
B語言由貝爾實驗室于1969年所發明。它的設計受到了Fortran和BCPL的影響。
B語言實際上就是去除了Thompson所認為的無用元件的BCPL系統,以便使得它能适合當時微機的記憶體容量。
http://en.wikipedia.org/wiki/B_(programming_language)B引入了+=操作符(盡管應該念成=+),以及自增/自減操作符(++和--)
printn(n,b) {
extrn putchar;
auto a;
if (a=n/b) /* assignment, not test for equality */
printn(a, b); /* recursive */
putchar(n%b + '0');
}
C
C語言就是是B語言加上了Pascal裡面的一些好的特性所組成的。它由Dennis Ritchie于1969年到1973年間在貝爾實驗室所發明。
C語言應該是最重要的一門語言了。它獲得了前所未有的成功。
除此之外,許多語言都是在C的基礎上進行設計的,包括:
C++(1976)
Objective-C(1986)
Perl(1988)
Java(1991)
Python(1991)
JavaScript(1995)
PHP(1995)
C#(1999)
Go(2007)
等等
Simula
挪威的仿真語言Simula I和Simula 67——從文法上來講——是ALGOL 60的完整的超集。
它的影響非常深遠。Simula以ALGOL 60為基礎,并添加了對象的概念,是以它也被認為是第一門面向對象的程式設計語言。
Simula 67(于1967年釋出)引入了對象,類,繼承和子類的概念,同時還有虛函數,協程,以及離散事件模拟。
這還不止,它還引入了垃圾回收的特性。
它的程式是這樣的:
Begin
Class Glyph;
Virtual: Procedure print Is Procedure print;
Begin
End;
Glyph Class Char (c);
Character c;
Begin
Procedure print;
OutChar(c);
End;
Glyph Class Line (elements);
Ref (Glyph) Array elements;
Begin
Procedure print;
Begin
Integer i;
For i:= 1 Step 1 Until UpperBound (elements, 1) Do
elements (i).print;
OutImage;
End;
End;
Ref (Glyph) rg;
Ref (Glyph) Array rgs (1 : 4);
! Main program;
rgs (1):- New Char ('A');
rgs (2):- New Char ('b');
rgs (3):- New Char ('b');
rgs (4):- New Char ('a');
rg:- New Line (rgs);
rg.print;
End;
Smalltalk
Simula對Alan Kay的影響極大——他曾經就職于Xerox PARC,并于1972年開始研發Smalltalk。
Smalltalk最初是設計給小孩用的。它在真實環境下做了充分的測試,并進行了數次重構。它曆經了多次改版在首次釋出8年後才最終面世。
Smalltalk是一門偉大的語言,它是第一個真正的現代面向對象程式設計語言。
由于它的文法很難掌握,是以它一直也沒能流行起來。然而,它幾乎對所有的現代程式設計語言都産生了影響。Objective-C, C++, Java, C#, Eiffel, 和Ruby基本上都是C和Smalltalk的混合體。
下面這個例子示範了Smalltalk版的控制結構:
result := a > b
ifTrue:[ 'greater' ]
ifFalse:[ 'less or equal' ]
Self
這是Smalltalk所影響的又一門語言——它也是在Xerox PARC中研發的——它就是Self)。
Self的設計目标是為了提升性能。它以Smalltalk為原型,并去掉了其中類的概念,以便運作速度能更快。
它沒有使用類的概念,而是用到了原型:Self允許對象可以不通過類而直接繼承自其它對象。
你可能也猜到了,JavaScript正是受它所影響的語言之一。
Scheme
Scheme是基于Actor模型設計的。Actor模型最早是1973年提出的,剛出現的時候被認為是個很前衛的概念。它是LISP語言)的一門方言,LISP是MIT于1958年所設計的一門人工智能語言。
它包含尾遞歸,詞法閉包,以及許多很酷的特性。
示例:
;; Calculation of Hofstadter's male and female sequences as a list of pairs
(define (hofstadter-male-female n)
(letrec ((female (lambda (n)
(if (= n 0)
1
(- n (male (female (- n 1)))))))
(male (lambda (n)
(if (= n 0)
0
(- n (female (male (- n 1))))))))
(let loop ((i 0))
(if (> i n)
'()
(cons (cons (female i)
(male i))
(loop (+ i 1)))))))
(hofstadter-male-female 8)
===> ((1 . 0) (1 . 0) (2 . 1) (2 . 2) (3 . 2) (3 . 3) (4 . 4) (5 . 4) (5 . 5))
E語言
E語言揉合了Java與Joule,它是一門專為安全相關的應用程式所設計的語言。
它以Actor模型為基礎,并實作了能力對象模型。
def makeMint(name) :any {
def [sealer, unsealer] := makeBrandPair(name)
def mint {
to makePurse(var balance :(int >= 0)) :any {
def decr(amount :(0..balance)) :void {
balance -= amount
}
def purse {
to getBalance() :int { return balance }
to sprout() :any { return mint.makePurse(0) }
to getDecr() :any { return sealer.seal(decr) }
to deposit(amount :int, src) :void {
unsealer.unseal(src.getDecr())(amount)
balance += amount
}
}
return purse
}
}
return mint
}
JavaScript
終于說到它了。
JavaScript已經成為了一門非常重要的語言。在能通路到網絡的裝置裡總會出現它的身影,它是WEB平台的頂梁柱,也是絕大多數WEB應用及移動應用的基石。多虧了Node.js,它現在也活躍到了服務端開發中。
JavaScript是基于Java, Scheme與Self來設計的。
它最初是由Netscape公司開發的,原本是希望實作一套類似于蘋果公司的HyperCard的東西——這是蘋果公司的Macintosh與IIGS電腦上的一款應用程式以及程式設計工具,它可以使程式開發變得更為簡單——Netscape把它內建到了浏覽器裡。
它的作者Brendan Eich希望基于Scheme來進行設計,但Netscape的管理層認為大家不喜歡Scheme的文法,并要求他将其設計得與Java更像一點。
JavaScript綜合了Java的文法(要不就不叫JavaScript了),Scheme的函數模型,以及Self的原型的特性。
由于Netscape公司的推動,它僅花了兩周時期便實作完成并釋出了出來。
- - - -