lisp、閉包與 scheme

傳統 lisp 是動態作用域,沒有閉包的概念, 但現代詞法作用域 lexical scope 似乎是主流。 其實回到最初,是沒有 scope 這個問題的。 lisp 就只是一個純粹的用列表表示的語言, 似乎動態作用域才是主流。

程式的直覺或人的直覺

一群鼓吹函數式編程與 lexical scope 的人創造了 scheme; 到現在另一大 lisp 分支 common lisp 也採用了動態作用域。 我也一直以為 scheme 較先進, 直到我讀了 lisp 之根源 , 才知道 lisp 並不是有意的選擇了 dynamic 或 lexical, 而是他什麼都沒做,便成了 dynamic。

似乎 dynamic 是較自然的作法, lisp 最初很簡單的把函數表示為一個列表, 自然沒有多餘的地方放所謂閉包。 lexical 則是要在每一函數宣告時, 將目前的 scope 保存一份到函數內。

這似乎是友善或優雅的對立。 dynamic 的實現較簡單直覺優雅,但使用上為人詬病; lexical 的使用直覺,但實作上有難處。

函數命名空間與函數的內涵

lisp 還有另一個我不喜歡的地方, 把函數和變數的命名空間分開放, lisp 之根源也是這樣做的。 後來發現他這樣做是 對函數的保護

因為如果照上所述,單純用列表達函數, 又把函數和變數放在同一命名空間, 那當使用者就會看到函數只是單純的列表, 而且無法分別函數與列表。 (或者是就單純把用 'lambda 開頭的列表都當作函數。) 但如果把這二者命名空間分開, 使用者就根本接觸不到函數了。 (要不要提供 function-quote #' 又是另一回事了; 雖然用 lambda 宣告暱名函數時還是看得到。)

至於要不要讓使用者看得到函數, 有些人不喜歡程式暴露內部狀態; 但我是認為應該要暴露的, 使用者應該要能知道程式在做什麼,以及知道自己想幹什麼。