2014年9月21日 星期日

sicp metacircular evaluator (5) - define

終於要談 define 了。為什麼談 define 要先談 lambda? define 有兩種型式:

define-exp L2 很單純, 就是把 a=5 加入環境中就好。但是 L1 的型式會建議一個 function。這就是 lambda 要做的事情。我本來也以為 define 很簡單, 先看了 define, 結果還是要回頭看 lambda。

define-exp
1 (define (plus4 y) (+ y 4))
2 (define a 5)

define-exp L1 會建立一個 procedure object, 這是一個 pair, 一個代表 procedure 本身, 就是

(y) (+ y 4)

例外一個就是一個環境指標, 指到哪個環境呢? 因為是在 global environment 執行 (define (plus4 y) (+ y 4)), 所以這個環境指標指到 global environment。

在 simple scheme (by c++) 的實作中, 我把這個環境指標存到 (y) (+ y 4) 這個 lambda procedure 中。

再來就是把 plus4 和 procedure 本身做個對應, 加到 global environment。這樣 plus4 就可以在 global environment 找到。繞如下面表格紅色部份。

new frame

((plus4 false true car cdr cons null? + *) (procedure (y) ((+ y 4))) #f #t (primitive #[compiled-procedure 2 (list #x1) #x3 #x4d655]) (primitive #[compiled-procedure 3 (list #x2) #x3 #x4d64e]) (primitive #[compiled-procedure 4 (list #x3) #x3 #x4d648]) (primitive #[compiled-procedure 5 (list #x5) #x3 #x4d639]) (primitive #[arity-dispatched-procedure 6]) (primitive #[arity-dispatched-procedure 7]))

new frame 的結果是從這段程式碼當中印出來的。

(define (add-binding-to-frame! var val frame)
(set-car! frame (cons var (car frame)))
(set-cdr! frame (cons val (cdr frame)))
(display "\nnew frame:\n")
(display frame)
(newline))

define-exp L2 很簡單, 把 a 和 5 找出來, 加入到目前的環境就好了, 一樣, 目前的環境是 global environment, 所以用 c++ std::map, map["a"] = 5 這樣就解決了。

在 sicp metacircular 的實作中, 類似 new frame plus4 的作法。

沒有留言:

張貼留言

使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。

我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。