Skip to main content

學術探討系列:型別推論(一) Type inference(I)

· 4 min read
戈頓
Developer & Co-founder of Tecky Academy

本篇是學術探討系列的第一篇,與先前不同的是內容上會以純粹學術角度集中探討一些題目,打響頭炮的將會是關於型別推論(Type inference)。歡迎大家留言建議一些題目啊。

靜態x型別 vs 動態型別

在Programming 的世界,自古以來已有兩大陣營:靜態型別(Static Typing) 及 動態型別( Dynamic Typing),以下將會簡稱為Static 及Dynamic。Static 的歷史較久,由 Fortran 至 Cobol 、C 至 C++ 、 C# 至 Java ,都是Static 陣營的中流柢柱。Dynamic 陣營在八九十年代開始變得受歡迎,亦由於簡單易學成為初學者的最愛,最受歡迎的 Javascript 、Python 、PHP 皆是Dynamic 陣營的代表 。

Dynamic vs Static

圖片來源:https://blogs.agilefaqs.com/

如何分辨Static 跟 Dynamic 陣營呢? 其實Static 跟Dynamic 所描術的是變數的type。

靜態型別

例如以下一段code,可見變數name以及names都分別定義為 String 及 List<String>,好處是Editor/IDE 能夠顯示所屬類別的method 和property。但明顯表達得相當累贅,由其是第二行,List<String> 跟 ArrayList<String> 各出現一次,相當囉囉嗦嗦。 而之後亦不能夠將變數改為其他type,因此是變數的type是Static 的。

String name = "John Doe";
List<String> names = new ArrayList<String>();
names.add(name);

Java Code例子

動態型別

同樣的feature ,在Python 實現就簡單得多,以以下一段code,可以看見只需寫下variable的名字,表達得亦相當自然。問題是其實未到運行一刻,亦不會知道type上是否正確。names 是否有一個叫 append 的method 此類問題在實際運行前一概不知。 而亦可以隨便將變數改為其他type,因此變數的type是Dynamic 的。

name = "John Doe";
names = [];
names.append(name);

Python Code 例子

正是兩者各有優劣,因此往往圍繞這個問題的討論都會非常熱烈,而兩個陣營各有支持者:

  • Static 陣營支持者覺得Dynamic 陣營的Code普遍欠缺結構,亦欠缺應有的Validation。
  • Dynamic 陣營支持者覺得Static 陣營多此一舉,Code size 亦因而較大。

型別推論出場

型別推論(Inferred types) 其實是正好在Static typing 跟 Dynamic Typing 中間,既有Static Typing 的 type checking。 亦有 Dynamic Typing 的靈活性。

以以下一段Code 為例,可以看見除了多出來的 let 及 type definition string[]之外,其實與 Dynamic Typing 相差無幾。

let myName = "John Doe";
let names: string[] = [];
names.push(myName);

Typescript Code 例子

型別推論運用的一個相當有效率的算法,名為 Hindley-Milner Type System 。此算法能有效從expression的數值推論variable的type。例如上面 let myName = “John Doe”,H&M Type system就足以推論 myName必然是string。

正因如此,新興的程式語言包括 Go 、Kotlin、Swift等都將Type inference 加為一個重要功能。

本篇已約略介紹型別推論的由來與背景,如大家有興趣瞭解,請踴躍留言!