1. 程式人生 > 其它 >程式語言史話,為什麼程式設計中 1=2?

程式語言史話,為什麼程式設計中 1=2?

   

考慮以下程式碼:

a = 1

a = a + 1

print(a)

你寫程式碼時候是不是也疑惑過,為什麼程式碼中會有a = a + 1,這個怎麼解釋?這就不是在說1 = 2麼?

這是一個對程式碼中"="常見的誤解,"="應該表示相等,但是它在此真意義是賦值。

小編也認為這是不好的表示法。我也知道一些語言不會用a = a + 1寫法,而是寫成a:= a + 1。為什麼不是規範起來呢?

通常的答案是"因為C"。但這只是一個小小的過失。為什麼C這樣做?讓起來回顧下找下原因。

四位老哥

在上個世紀60年代早期,主要有四種主要的高階語言:COBOL,FORTRAN II,ALGOL-60和LISP。當時賦值過程要分成兩步:1、定義變數時候初始化2、已有變數值改變時候重新賦值。以開頭我們的Python例子,我們有:

a=1 #初始化

a = a + 1#重新分配

print(a)

人們沒有使用這些特定的術語,但它捕捉到了每個人都在做的事情。以下是四種語言的操作符情,以及進行相等判斷的檢查:

ALGOL沒有專門的初始化操作符。你先得建立一種型別的變數,然後使用運算子賦值給它。你可以做整數x;x:=5;但是你不能直接就x:= 5;,所以 FORTRAN是唯一一個用=做各種操作的語言,更像是現代語言的行為。但是我們知道歷史上,C從ALGOL傳承下來,所以:=賦值被刪除了,並且把=作為了相等檢查。

由ALGOL到CPL

ALGOL60可能是電腦科學史上最具影響力的程式語言,單也可能是最無用的語言。該語言按設計總核心規範中沒有任何I/O特性。你可以對輸入進行硬編碼並測量輸出,但如果你想用它做任何事情,你就得有一個擴充套件核心語言的編譯器。 ALGOL是專為研究演算法而設計的,你還想要做其他事情,它就會崩潰。

然而,它確實是一種強大的語言,人們希望將其推廣,想在商業和工業使用。 1963年,克里斯托弗斯特拉奇和劍橋大學進行了第一次大推動。建立一個新語言CPL,CPL是在ALGOL之上增加了一大批創新,其中大部分是讓我們後悔的特性。這其中一個就是初始化定義,其中一個變數可以在同一個語句中初始化並賦值!而不是寫整數x;x:=5;你可以直接用x=5。

但是我們從:=演變到=,主要是因為CPL支援三種變數初始化:

=表示按值初始化。

表示通過引用初始化,以便如果xy,重新分配給x也會使y變異。但是如果你寫了xy + 1並嘗試重新分配x,程式就會崩潰。

≡表示通過替換來初始化,也就是使x成為一種在每次使用時都對RHS進行評估的niladic函式。他們從未解釋如果你嘗試重新分配給x可能會發生什麼。

問題:現在=用於初始化和相等。幸運的是,CPL在實踐中對此表現得很清晰,你要寫=的任何地方你的意願都明確無誤的。

僅僅一年之後,Kenneth E. Iverson發明了APL,它將<-用於賦值。由於大多數鍵盤都不具備這一點,甚至連Iverson都沒咋用過它,他的後續語言J則使用=:作為賦值。但是,APL深深地影響了S,S又深深地影響了R,這就是為什麼<- 是首選的R賦值運算子。

由CPL到BCPL

CPL是一個很棒的語言,只有一個小問題,沒有人能夠實現它。少數人包攬了部分功能子集的部分實現,但對於那個年代的編譯器來說,這太大而且太複雜了。因此,馬丁理查德剝離了很多創造BCPL的複雜性。第一個BCPL編譯器於1967年推出,並於1970年成為第一個CPL編譯器。

除了其他簡化之外,"三種初始化"規則被去掉了。Richards認為替代表達是適當的,可以被函式取代,並且與賦值相同。所以他把它們全部簡化成一個=,但是命名全域性記憶體地址,它使用了:。與CPL一樣,=也是相等判斷。對於重新賦值,他使用:=就像CPL和ALGOL一樣。很多後來的語言遵循這個約定,=用於初始化,:=用於重新賦值,還有=用於相等判斷。但是當Niklaus Wirth創造Pascal時它就成為主流,這就是我們現在稱之為"Pascal風格"的原因。

在我記憶中,BCPL還是第一個"弱型別"語言,因為唯一的資料型別是資料字。這使得編譯器更容易移植,導致更多的邏輯錯誤,但是Richards希望更好的流程改進和描述性命名能夠抵消它。 另外,BCPL還引入了大括號作為定義塊的一種手段。

由BCPL到 B

Ken Thompson希望將BCPL轉換在PDP-7上執行。雖然BCPL有一個"小型編譯器",但它仍然是PDP-7的最小工作儲存器的四倍,因為PDP-7的儲存器只有4k至16kb。所以Thompson需要建立一個新的,更小的語言。另外他個人審美上也希望儘量減少原始碼中的字元數。這最終成為B設計的最大因素。這就是為什麼我們有例如++和--操作符的初衷。

一旦你擺脫了命名的全域性記憶體地址,BCPL總是使用=進行初始化,使用:=進行賦值。Thompson決定將它們合併為一個單一的標記,用於所有形式的任務,並且選擇了=因為它更短。但是,這這樣一來確定它的用意就有點含糊不清:如果x已經被宣告,那麼x=y是一個賦值還是一個相等性檢查?而且在某些情況下,它應該是兩者皆有!他添加了一個新的標記==,作為"等於"的唯一形式。正如Thompson所說的那樣:

由於賦值的使用頻率在一個典型程式中的大概是相等判斷使用次數的兩倍,所以操作符長度要減半才是最合適的。

Thompson(由Dennis Ritchie加入)在1969年左右釋出了B語言的第一個版本。在同期兩個人Ole Dahl和Kristen Nygaard發明了第一個OOP語言Simula 67。 Simula遵循ALGOL嚴格分離的初始化和賦值步驟的約定。Alan Kay也在這個時候也創造smalltalk,也遵循了同樣的語法,還增加了塊。因此,直到1971年左右,大多數新語言都使用:=進行賦值。

由B產生了C

剩下的就是大家比較熟悉歷史。。。。。

還有一點需要補充的是,在隨後的一年ML語言出現了,是第一真正強調純函式式的語言。但它仍然在引用單元中有一個列外的設定,可以使用:=賦一個新值。從1980年開始,我們開始看到正確導向的命令式語言,特別是Eiffel和Ada,它們都使用:=來賦值。

從整體來看,=從來不是自然選擇的賦值運算子。幾乎ALGOL所有分支中的每個語言都使用:=來代替賦值,可能是因為=與等式相關聯。現在大多數語言使用=,完全是因為C使用它,並且我們可以使用C向前追溯,是CPL第一個這樣吃螃蟹的。