Scheme 程式設計/什麼是 Scheme?
每當我們閱讀有關 Scheme 的內容時,我們經常會聽到“函數語言程式設計”這個詞;這是真的。Scheme 是最早有效支援這種正規化的語言之一。函數語言程式設計意味著,當我們用 Scheme 程式設計時,我們儘量避免“副作用”;我們不會像分配變數時那樣頻繁地改變變數的值。實際上,所有執行此操作的 Scheme 部分都以“!”結尾(稱為感嘆號),這已經暗示了你做錯了,除非你知道你在做什麼。然而,Scheme 並不是“純函式式”的,因為它確實“允許”副作用,只是不鼓勵它們。在 Scheme 中,所有東西都是表示式;Scheme 程式最好被視為一個長而複雜的表示式;我們之前看到的詞法 `let` 塊是一個表示式,因為它會計算出一個值。例如,我們可以將整個塊用作 `if` 表示式的條件,這比一些人預期的要常見。
函數語言程式設計的另一個共同特徵是,當然,函式和過程比大多數其他編譯語言中的功能更強大。在 Scheme 中,過程是一級物件;你可以對它們執行與對 C 中的整數相同的操作。你可以將它們傳遞給過程、從過程返回它們、將它們儲存在變數中,或者在執行時將它們計算為表示式的結果。
Scheme 也像大多數語言一樣,具有詞法作用域。這意味著過程在程式碼中的定義位置決定了它們的行為方式,而不是它們被呼叫的位置。這似乎顯而易見,因為如今所有語言都具有詞法作用域,但這一點很重要,因為 Scheme 是最早強調詞法作用域重要性的語言之一,這催生了閉包,如今它們在許多解釋語言中得到了廣泛實施。
Scheme _沒有_ `while` 迴圈或 `for` 迴圈。在 Scheme 中,透過簡單地讓過程呼叫自身就可以實現類似的效果。“這不是效率低下嗎?”有些人會問,答案是“不!”因為 Scheme 還以 _適當的尾遞迴_ 的使用為特徵,並開創了這一使用方式:每當過程以這樣的方式呼叫自身,即相同的效果可以透過迴圈或迭代來實現時,Scheme 保證編譯器會將它重寫為機器碼級別的迴圈,因此你永遠不會用完堆疊空間,也不需要浪費時間呼叫過程,因為你嘗試做的事情可以重寫為迴圈。
我們已經在上一節中看到,Scheme 可以擴充套件自己的語法。這是因為 Scheme 像任何 Lisp 變體一樣,具有一個非常重要的屬性:語言是同像的;程式本身與其操縱的資料之間沒有本質區別。我們已經討論了 Scheme 原始碼中大量括號的問題。這是有充分理由的:Scheme 中的主要資料結構稱為 _列表_(因此得名:LISt 處理器),Scheme 原始碼本身也只是一個非常複雜的列表。列表可以包含其他列表,並且由於資料可以重新排序,Scheme 可以輕鬆地在編譯時和執行時重寫自己的原始碼和指令,這就是語法擴充套件的實現方式。
但是,如果 Scheme 是第一個做這麼多重要事情的語言,那麼 Scheme _老_ 嗎?是的,它很老;它是現今仍在使用的最古老的語言之一,這既可以被看作是它已經過時了,也可以被看作是它已經證明了自己的價值。