類型系統(type system)是一門編程語言最核心也是最基礎的部分。無論該語言基於何種編程范式,都必須在開天辟地之初首先對類型系統作出明確的定義。這是因為,編程語言雖然五花八門,千奇百怪,但是歸根結底,編程語言最終的目標,本質上無非是回答兩個問題:
無論是面向過程的編程語言、面向對象的編程語言、函數式編程語言、並行編程語言或者其他任何千奇百怪的編程語言,其根本性的終極目標,就是回答以上兩個問題。各種編程語言之所以差異頗大,其實就是對這兩個問題給出的答案不同導致的。
在如何表示信息這一問題上,編程語言通常需要定義一些“基本存儲單元”,作為整個語言世界的基本構成要素。這種思想很類似於我們對物理世界的認識——宇宙雖然鬼斧神工,豐富多彩,但是在微觀上,整個世界僅僅是由少數寥寥幾種基本粒子構成的(物理細節不必深究,這裡只是打個比方)。但是奇怪的是,基本粒子就只有幾種,為何卻能構成地球、水、人、樹、風這些看似截然不同的東西呢?答案在於,基本粒子雖然不多,但是自然界確立了一套簡單而精妙的組合規則,使得基本粒子能夠以許多種不同的方式組合在一起,由於組合方式的不同(結構差異),組合規模的不同(數量差異),導致了最終宏觀表現的不同。
與現實物理世界類似,一門編程語言就確立了一個獨特的“世界”,這個世界可能豐富多彩,千奇百怪。但是就如我們現實世界一樣,繁雜的外表之下,骨子裡都是由一些“基本粒子”,按照一定的組合方式構成的。那麼究竟有哪些基本粒子,又允許進行何種組合,對編程語言所確立的世界最終的宏觀結果影響非常巨大。甚至可以說是根本性的。
有一定編程經驗的程序員,往往對類型系統不太關心。他們更感興趣的是語言的其他特性,例如並行計算能力,編程風格,類庫等等。這些特性當然非常重要,就生產環境的應用來說,語言特性甚至是處於次要地位的。類庫被許多程序員認為比語言本身更重要。然而,堅實的應用是以對語言深刻的理解為基礎的,花費一些時間對語言的本質進行研究,會對深入理解語言背後的設計考慮有很大的幫助。也能讓我們避免陷入語言的陷阱,或者陷入與別人的口水戰之中。
回到對類型系統的考慮,那麼究竟什麼是類型系統呢?
一門語言定義了一套基本類型的“集合”,這個集合就作為一個整體被稱為類型系統。這一稱謂中,涉及到兩個關鍵詞——“類型”和“系統”。
什麼是“類型”?
計算機存儲是以二進制方式進行的,並以連續的八個二進制位為一個基本單元——“字節”。從這一點來看,計算機存儲是通用的,存儲人類的文字或者存儲圖像、聲音或其他別的媒介都沒有內在的本質差異。但是奇怪的是,在編程語言概念上,卻總是會引入一系列的大相徑庭的“基本類型”。例如,int和double,一個存儲整數,一個存儲浮點數。如果我們考慮一下,就會發現其實int和double本身並沒有什麼差別,都只不過是若干個字節構成的存儲單元而已。那麼對他們進行區分意義何在?其實就“存儲”概念而言,我們用二進制方式,以字節為單位來實現信息的存儲,已經給出了信息表示的“終極答案”了。但是完成存儲,只是整個計算機系統功能的一部分。如果僅僅是把信息存儲,而不進行計算,那麼計算機就不叫計算機,改叫存儲機了。可見,問題的實質在於,我們要存儲,更要計算。
int和double都是幾個字節構成的,但是其運算規則截然不同,差異巨大。同樣的,string和int或double也不相同。我們在string上進行拼接、刪減、搜索、替換。但是在int上進行加減乘除。這些計算需求和內部實現上的差異,迫使我們的語言層次上進行明顯的區分。
上面舉的類型,都是來自C家族語言中的概念。但是我們也知道,在一些語言中,不需要我們對類型進行顯式的說明。但是不說明不代表不存在。只不過一個是程序員顯式聲明,一個是編譯器(或解釋器)自主推導;一個是把責任推給程序員,一個是把責任推給編譯器作者。類型系統總是內在的存在的。永遠沒有被去除。
什麼是“系統”?
坦白講,這是一個非常模糊的概念。我們會說操作系統、消化系統、生態系統……各種各樣的系統,然而對於系統本身是什麼,在不同的科學領域有截然不同的定義。通常我們所說的系統中,存在一些基本要素(軟件模塊、細胞、物種等等),然後存在一定的相互作用關系(函數調用、細胞連接、捕食與被捕食等等),在此基礎上實現一定的功能(完成金融計算、排解人體毒素、完成有機物的自然循環等等)。那麼我們就把這些基本元素,以及其構成方式,統稱為一個系統。
之所以說“系統”是個模糊的概念,原因在於,這一概念本身並非原子概念,一個系統,也可能再分解為一系列的子系統,例如操作系統就可以分為輸入輸出子系統,繪圖子系統等等,人體內的消化系統也能夠分解為一系列的子系統。而子系統又可在更小的級別進行分解。系統的劃分是相對的,系統的構成也是相對的,因此其本身常常是模糊的。
這麼說來,如果要追究系統一詞的內涵,會很困難。但是在我們討論的編程語言這一領域內,當提到“類型系統”時,系統其實就是指:
這兩點合起來,就成為了我們的“類型系統”。只要做到這兩點,就已經非常強大了。這其中,“基本類型集合”是一個非常小的有限集合,也就寥寥幾個元素,而“組合、運算、轉換”等規則,也是一個較小的有限集合。但是通過選擇不同的元素進行組合,這兩個有限的集合之上,卻衍生出了一個無限集合——“類型空間”。
理解這一點非常關鍵。因為這恰好符合了我們對自然界構成的認識——有限的若干種基本粒子,有限的若干種基本規則,結果卻是無限可能性的巨大世界。
這一簡單優雅而驚人的世界構成觀,貫穿了人類現實世界和計算機編程語言所定義的虛擬世界。或許語言的設計者也沒有料想到,但是最終的結果確實是有限的設計導出了無限的可能性。
所以,當認識到這一點之後。就再也不會輕視類型系統,再也不會把類型系統看得簡單,自以為十分了解了。而類型系統設計上的細微差異,最終也會導致截然不同的類型空間,導致對信息表達方式的巨大差異。那麼還有什麼理由不認真的研究這一基本要素的呢?還有什麼理由讓我們逃開這一許多程序員認為“簡單”的主題呢?