這裡談的是 sicp metacircular evaluator 的 environment, 什麼是 environment?
ref:
http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-26.html#%_sec_4.1.3
下面是個簡單的示意圖, 我不確定一個 environment 只有一個 frame, 還是可以有多個 frame, 我的 c++ 版本的 scheme interpreter 一個 environment 只有一個 frame。如有有新環境的話, 會有一個指標對應到上層環境, 當然不一定要指標, scheme 就沒有指標可以這樣做, 它是用 list 來做類似的事情。當目前環境找不到變數定義時, 就到上層環境找, 都找不到才可宣稱此變數無定義。
environment (frame sequence)
frame 1 => table [variables = values; ex: a = 5, b=6] |
frame 2 => table [variables = values; ex: + = add_proc, b="iamstring"] |
frame 3 => table [variables = values; ex: - = sub_proc, b=1.2.3] |
|
以下的程式碼便是建立 global environment。
環境就是建立一個變數和變數值的對應, 幹什麼用呢?
(+ 1 2)
當要處理這個 expression 時, expression 我看過一些翻譯: 表達式、算式, 不過這裡我把他翻譯作 "運算式", 再回到我們那個運算式, 1, 2 是數字沒問題, 那 + 這個符號是什麼呢?
你說它是什麼就是什麼, 不過一個正常人都會把 + 解釋成加號 (如果你看到 + 會想到
減法, 那說明你的品味很獨特), 所以這個運算式就是把 1, 2 加起來。那怎麼讓 + 對應到加法呢? 把
+ 當成
變數,
加法當成
變數值對應起來就好。
所以 frame 裡頭有一個 (+, 做加法的函式) 這樣一個對應。在 c++ 裡頭, 用 std::map 就可以搞定這件事情。
不過 scheme 沒有 map, 只有 pair, 所這個程式用了另一種辦法。
e1 L6 是變數 (variables), L7 ~ 11 是這些變數的值 (values)。這個程式碼把變數保存在一個 list, 變數值保存在另外幾個 list, 如果是 primitive procedure 就加入 primitive 來識別他是一個 primitive procedure。
env.scm L300, L301 則把 true, false 加入這個環境的第一個 frame。
所以裡頭有: false, true ... 這些 name, 還有 primitive procedure, 下面框框的紅色部份, 以 primitive symbol 開頭, 後面奇怪的東西就是 primitive procedure。
(ex:
#[compiled-procedure 12 (list #x2) #xf #x321917])
這個就是 global environment, 一開始就會有的環境, 也是所有子環境的父環境。今天不談子環境, 單純談 global environment。
有了 environment 之後, 遇到 symbol (variable?) 時, 就可以來查這個 environment 有無對應的值。下面的 lookup-variable-value 就是在做這件事情。從 L260 開始執行起。可參照 sicp 中文版 p261
對環境的操作一節
(display (lookup-variable-value '+ the-global-environment)
會回傳
(primitive #[arity-dispatched-procedure 15])
這個 list。
'primitive 和 + 這個 procedure。
把回傳的 + procedure 和 (1 2) 作為 apply 的參數 (這個 apply 是 scheme 的 primitive procedure, 不是 metacircular evaluator 程式碼裡頭那個 apply), 就可以計算出 3 來。用 c++ 實作的話, + procedure 會是一個 function, 把 1, 2 作為參數傳給這個 function 即可。
你如果想要惡搞 +, 把 + 對應到 - procedure, 就可以得到 (+ 1 2) = -1 的奇怪結果。
(define aa 5) 會把變數 aa 對應到 5, 因為這個 define 是在 global environment, 所以 aa 會被加入到 global enviroment。有了環境之後, 應該也可以實作 define 了, 不過 define 比你想像得還要複雜。
下次再談 define, 不過要談 define 得先談 lambda。
沒有留言:
張貼留言
使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。
我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。