« Home

何謂 elaboration? [cs-0004]

elaboration 指的是轉換沒有語意的表面語法(surface syntax 或是說 source code)到有語意的語言表示(language representation)的過程,這樣講可能有點抽象,所以需要一些例子。試問 foo(a, b) 這段 Go source code 有語意嗎?事實上是沒有,因為只有在 Go compiler 經過

  1. 讀取文字
  2. 解析語法取得語法樹
  3. 型別以及其他檢查

現在這段程式碼才會在 Go compiler 內部用某種資料結構表示,而 Go compiler 可以相信這段程式碼是滿足 Go 規範的程式,這樣才是有語意的語言。這個觀點一開始對你來說可能蠻怪異的,但我們可以仔細來看這樣定義的好處

  1. 有些語言如 Fennel https://fennel-lang.org/ 刻意把自己變成另一個語言 Lua 的另類文法,在語言表示層面要求共用一樣的語意。Fennel 還支援了 macro 系統
  2. 語法可以作為片段,嵌入到任何位置,只不過後續的檢查階段可能拒絕嵌入後產生的語法,因為這樣產生的程式依然可能是語法或是語意不正確的,比如使用 C 語言的 preprocessor 寫程式就經常會遇到這樣的問題。能把語法記錄下來並在別的地方展開的程式就叫做 macro,LISP 的 elaboration 經常叫做 expander

Macro system [cs-0005]

雖然 C 的 preprocessor 也被稱為 macro,但跟 LISP、Elixir、Julia 比起來就差很多的原因是

  1. C 對語法的原始位置放棄追蹤
  2. C 對 macro 的輸入跟輸出都沒有基本的檢查,也沒辦法對不同輸入做出反應

而常見的 LISP macro 過程則是:

  1. reader: TEXT -> S-expression
  2. 使用者定義的 macro: S-expression -> S-expression
  3. expander: S-expression -> LISP

elaboration 前對語法樹進行操作的能力就是 LISP 最大的特徵,這使語言使用者可以自行發展他想要的語法,Clojure 做得比傳統 LISP 更好的地方就是這裡它採用的 edn 能表示比 S-expression 更多的資料,如 hashmap。