-
1 # 學好玩
-
2 # 思考思考的動物
▇ 首先,我們需要搞清楚型別的由來。
程式語言中所謂的型別,具體指的是資料(包括物件)的型別。資料型別的產生有概念和物理兩個方面因素:
概念因素:資料因其本身內容在中我們腦子裡對應的數學概念不同而進行的分類,常見型別有:數字(正整數、整數、小數、複數)、布林、字元、符號、空、以及各種資料結構(字串、陣列、向量、列表、字典、集合、函式、... ),這些型別是在我們長期的數學應用中就形成的,是對外部概念的抽象;物理因素:我們在計算機語言中所定義的資料,最終需要實現在物理機器上,而非僅僅是大腦中的數學概念,這就要求,知道資料的大小、編碼格式、等 這樣的物理資訊,根據這些資訊就可以將資料分類,例如:C語言中,同樣是整數卻因大小不同而分為: char,short, long,long long,這些型別是因為物理實現而產生的;若,將所有計算機語言,按照接近程度,從機器到數學排成一列,則越靠近機器這邊的語言,其資料型別越受物理因素影響,例如:彙編、C/C++,反之,越接近數學的語言的資料型別越會圍繞數學概念進行設計,例如:Lisp、R、JavaScript。
▇ 接著,我們來看變數與資料型別的關係。
在所有計算機語言中,大體有兩種看待變數的方式:
變數是儲存資料的容器;變數是訪問資料的入口;● 採用第一種方式的計算機語言:
因為變數需要儲存資料,所以變數受其儲存的資料的型別制約。
將資料儲存到同類型變數的過程,稱為賦值。
在我們宣告變數時,計算機要給這個變數分配記憶體,這時,計算機至少需要知道這個變數將來的賦值資料的物理大小,於是,計算機語言,不得不要求,宣告變數時,必須指出其賦值資料的型別(包含物理大小資訊)。另一方面,根據資料型別對變數被分配的記憶體將伴隨它的整個生命週期,同時,在訪問變數中資料時還會使用資料型別,這就意味著,宣告時指定的那個本意是賦值資料的型別變成了該變數的型別,這就是所謂的變數型別。
這種,變數有型別的語言,稱為強型別語言。
● 採用第二種方式的計算機語言:
其變數僅僅儲存,資料在物件池中的,入口地址,而不儲存資料。將資料入口地址儲存到變數的過程,稱為繫結。我們在宣告變數時,計算機只需要分配一個儲存繫結地址的記憶體塊就可以了,無需知道將要繫結的什麼資料,於是變數也就沒有了型別。
這種,變數沒有型別的語言,稱為弱型別語言。
▇ 最後,我們來比較一下強弱兩種型別的語言。
早期,強型別語言,都是編譯(靜態)語言,例如:C/C++,Fortran,Pascal 等,這類語言,沒有強大的執行時來支援物件池,因此只能採用第一種方式。而早期,弱型別語言,都是解釋(動態)語言,例如:Lisp,Scheme 等,它們有強大的直譯器,其中包括物件池,因此可以採用第二種方式。
強型別語言,有一個非常大的優勢,那就是:編譯器知道變數的型別,可以提前檢查賦值錯誤,再加上,編譯語言的執行效能優勢,這使得,強型別語言,在上世紀中葉很快成了主流。但是,強型別的優勢也是缺陷,這就是:由於變數帶有型別,所以程式碼和型別強關聯,很難寫出同時適用於多種型別的程式碼,為了修補這個缺陷,幾乎同時出現了兩種解決方案:
從宏(模板)發展出來的泛型;面向物件(OOP);泛型使得,型別可以成為某個程式碼塊的引數,在使用該程式碼塊時被具體制定。
面向物件,利用繼承讓子類物件複用父類物件的程式碼塊。
在經過,泛型 和 OOP 改造後,強型別語言在千禧年前後,到達了頂峰,以至於這時,出現的 Java 和 C# 這樣的動態編譯語言,也採用強型別。
但是,弱型別語言並非一無是處:沒有變數型別是天然的泛型、OOP也可以引入、適用於指令碼程式碼,因此,才有 JavaScript 和 Python 這樣的 弱型別語言,隨著 計算機效能的飛速發生使得 強型別語言的效能優勢慢慢削弱,而弱型別語言的簡單靈活慢慢凸顯,這使得,如今的它們也正是 如日中天。
計算機源於數學,早在第一臺計算機出現之前,數學家就對可行性計算問題進行了深入的研究,先後出來了:遞迴函式、λ-演算、圖靈機,之後 圖靈機稱為了計算機體系結構的數學原理,而 λ-演算正是函數語言程式設計的本質。因此,我們可以從數學角度來稍微看一下變數(常量)型別。
在數學中,變數是有型別的,常見應用場景有:
場景一:對於 任意 x ∈ ℝ,... ,例如:對於任意 a, b, c, d ∈ ℝ,都有 (a² + b²)(c²+d²) ≥ (ac+bc)²;場景式二:令 x=1,..., 例如:令 K={(1),(1,2)(3,4),(1,3)(2,4),(1,4)(2,3)},則 S₄ 有正規群列 {e}⊲K⊲A₄⊲S₄;因此,強型別更符合數學,如場景一那樣,於是有些的新興強型別語言,會進一步吸收數學的特點,這些語言允許程式設計師不指定變數型別,它是透過上下文來推算出變數的型別,如場景二那樣。
變數是否有型別,僅僅是計算機語言的型別系統的一部分,即便是同為,強或弱型別語言,其型別系統也差距較大,以下是一些型別系統具有代表性的語言:
C語言,代表指令式程式設計,其型別系統以過程為核心進行設計;C++語言,代表傳統多繼承面向物件,其型別系統多繼承類-物件為核心;Java語言,代表傳統單繼承面向物件,其型別系統單繼承類-物件為核心,以介面彌補單繼承的不足;JavaScript語言,代表原型鏈單繼承面向物件,其型別系統建構函式-原型鏈為核心;Scala語言,代表加入特性的面向物件,特性的加入彌補的單繼承的不足;Lisp語言,代表傳統函數語言程式設計,其型別系統以符號表達式為核心;Haskell語言,代表加入範疇的函數語言程式設計,數學中的型別,就本質而言,就是基於集合(或者比集合更大的類)之上的各種數學系統,目前最大的代數系統是範疇,Haskell採用的就是以範疇為核心的型別系統;當然,型別系統,還包括宏和泛型,Scheme的衛生宏、C#的泛型,都是典型代表。
另外,除了型別系統外,計算機語言設計的另外一個重點,就是程式碼流程控制,例如:面向側面、懶惰模式、後繼體、等,按照控制流也可以對計算機語言進行分類。
如對於C語言的變數,我們有整型,實型,字元型等。那我們為什麼需要為程式語言設計變數型別這個概念?為什麼各種程式語言設計者不約而同地使用了【型別】這個概念,即使如Python這種不顯式指定型別的語言,一樣是強調型別這個概念。最初的程式語言設計者是如何想到,為【變數】設計【型別】這個概念呢?有了型別這個概念後,能為程式設計帶來什麼樣的好處呢?如果我們是最初的那批程式語言的設計者,我們能夠理所當然地想到為變數設計型別這一固有屬性嗎?為什麼?或者說,如果為變數放棄了型別這個概念後,是否同樣能夠設計一套理所當然的程式語言。我不知道我的問題表達清楚了嗎。這個概念,有種“百姓日用而不知”的那種感覺,一直在用,但說不清楚有啥好處。
回覆列表
也不是所有程式語言都是強型別,但是高階語言還是需要分型別,以便理解程式碼和查錯debug,以後都是人工智慧自動程式設計,型別也就不重要了。