Skip to content

Commit

Permalink
什麼語言容易自舉
Browse files Browse the repository at this point in the history
  • Loading branch information
MROS committed Sep 18, 2024
1 parent 3c8f4d1 commit 062985f
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 0 deletions.
1 change: 1 addition & 0 deletions book/.vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export default defineConfig({
{ text: "大品天仙訣之臆想", link: "/大品天仙訣之臆想" },
{ text: "序・去往新世界", link: "/序・去往新世界" },
{ text: "離塵第一步:自舉", link: "/離塵第一步:自舉" },
{ text: "什麼語言容易自舉", link: "/什麼語言容易自舉" },
],
},
],
Expand Down
31 changes: 31 additions & 0 deletions book/什麼語言容易自舉.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
## 編譯與直譯
只要學過計算機概論,大抵都對編譯與直譯有基本的概念。

常會有人把程式語言分類爲編譯式語言、直譯式語言兩類,其實這並不嚴謹,編譯與直譯並非形容「語言」,而是形容「語言的執行方式」。

舉例來說, C 語言通常被編譯成機器碼執行,但它也可以直譯執行,例如 [c4](https://github.com/rswier/c4) 就是個極簡 C 語言(子集)直譯器,才幾百行而已。

再舉個例子, Kotlin 官方就支援多種執行方式,可以編譯到機器碼、 JVM 字節碼、乃至於轉譯成 JavaScript 再交由 JavaScript 引擎執行。硬要將它歸類為編譯式或直譯式都不對,唯有把程式如何執行在機器上給具體描述出來,才有意義。

基本上,一個語言能被編譯,那幾乎都能被直譯,因為寫直譯器比編譯器要容易得多。而如 Python/Ruby/JavaScript 等動態語言則很難完全被編譯,即使真要編譯,由於動態語言中一個物件是否擁有某個方法是無法在編譯期判定的,所以在編譯出的執行檔中,勢必得加入厚重的運行時來即時維護物件資料、判定物件類型,但如此一來,還能算是編譯嗎?

總的來說,編譯跟直譯是很粗略的分類,要知道一份程式是如何執行的,終究得深入其編譯時跟運行時的細節才行。當吾人說某語言是編譯執行,往往代表其運行時相對較小,反之若說某語言是直譯執行,代表其含有沈重的運行時(通常得附帶整個直譯器)。

## 什麼語言容易自舉

帶有沈重運行時的語言難以自舉。以 Python 為例,它的官方實作是用 C 寫的直譯器 CPython。在這個基礎之上,能透過****寫 Python 完成自舉嗎?如果用 Python 寫了個 Python 直譯器,該直譯器仍然得運行在 CPython 上,兩層直譯執行會得到一個很慢的直譯器,而且無法擺脫 CPython。

要擺脫 CPython ,就得是用 Python 寫出 Python 編譯器才行,以此編譯器將自身源碼轉為機器碼,就不再依賴 CPython 了。但前一節提到的物件維護運行時怎麼要怎麼加進去呢?有兩種思路:

1. 手寫真言來實作運行時。
2. 定義一個不需要運行時的 Python 子集,用這個子集來寫運行時。

不管哪一種做法都需要額外的開發成本。

除了動態語言的物件/類型維護,垃圾搜集也是需要運行時的語言特性。有些語言如 Bash, JavaScript 還支援 `eval` 這種動態執行程式碼的函數,不把整個直譯器/編譯器包進編譯結果還真支援不了。

編譯時期的語法特性如模式匹配、和類型(sum type)以及各種語法糖都是編譯期(語法、語義分析)就處理完的,跟是否容易自舉的關係不大。當然,語言的能力越強,編譯器越複雜,但語言能力越強,編譯器又越好寫,該如何完成特性的迭代開發,這其中的折衷,大概也是自舉的樂趣所在吧!

TODO: 此節應補圖

小記:本章不少內容屬貧道自行推想,有錯請不吝賜教。

0 comments on commit 062985f

Please sign in to comment.