2014年9月27日 星期六

sicp metacircular evaluator (6) - lexical closure

sicp metacircular evaluator 這系列的文章瀏覽率慘不忍睹 (當然平常的文章也不怎麼樣, 只是這系列真的太慘了, 可以寫個「慘」字, 有一篇當時在首頁的文章, 3 天只有 20 個點閱率), 不知道是我寫的太爛了還是這題目太冷門了, 但我從中學到很多, 也很快樂, 這是苦澀後的甘甜。

我有想過類似 Gigacircle 那種醒人的標題, 例如: 什麼, 你還不知道什麼是 closure 嗎? 她讓我高潮了。或是 ... 你還不知道的 closure 妙用, 我獲得的 10 種美妙經驗。

但我實在不想用這些讓人耳目一新的標題, 好像有點庸俗。

希望這篇可以破紀錄, 怎麼破, 很簡單, 3 天低於 20 就成了。

這篇是這系列的最後一篇了, 沒興趣的讀者們請忍耐一下, 接下來我就會寫不同的文章了。

這是 define + lambda 的組合。

exp1
1 (define (aa x) (lambda (y) (+ x y)))
2 (define aa (lambda (x) (lambda (y) (+ x y))))

exp1 L1, L2 是一樣的運算式, define 一個 function 只是 lambda 的語法糖衣。這會建立一個 procedure object, 然後把 aa 對應到這個 procedure object, 並加入 global environment, 而這個 procedure object 還有一個環境指標指到 global environment。

不過這個 procedure 是傳回一個 procedure, 語法不是很好看, 我可是花了不算短的時間才弄懂。也就是人家說的 function 傳回一個 function, 我還是不知道和 c 傳回 function pointer 有什麼不同??

下面是一個示意的結果:

aa =>
( ( x , () ) ( ( lambda , ( ( y , () ) ( ( + , ( x , ( y , () ) ) ) () ) ) ) () ) )
env name: global

procedure 的參數是 x, lambda ... 那一串就是 procedure body; 環境指標指向 global。

exp2
1 (define aax (aa 5))

exp2 L1 這個運算式稍微複雜一點, 這個時候 aa 會被執行起來 (因為 aa 是一個 procedure), 所以會開一個新環境 e0, 把 5 對應給 x, 然後 aa 會傳回一個 function: (y) (+ x y), 這是執行後的結果, 傳回一個 procedure, 而 e0 就和這個 function 綁在一起, 不是綁定到 global environment。而 e0 的上層環境是 global environment。

至於變數 aax 對應到這個 procedure object, 存在 global environment。


result:
( ( y ,  ()  ) ( ( + , ( x , ( y ,  ()  )  )  )  ()  )  )
env name: e0
  e0 outer env name: global

exp3
1 (aax 6)

exp3 L1 這個運算是在執行 aax 時, 會開一個新環境 e1 (其上層環境是 e0, 因為 e0 和 aax 綁在一起), 6 會對應到 y, 而在執行 aax 時, 就會到 e0 找到 x=5, 就這樣把 x, y 都找到所對應的值。

那 lexical closure 是什麼, 已經講完了, 這就是 lexical_closure。

aax 除了一個 procedure 還有一個環境 e0, e0 裡頭記載著 x=5, 要不然你以為 aax 是怎麼能正確找到 x 的值。

這有一個翻譯稱為「閉包」, 應該是個中國術語, 台灣不知道有沒相關翻譯的辭彙, 中國術語以後會入侵的更厲害了。

2 則留言:

  1. (lambda (x)
    (lambda (y) (+ x y)))
    和C的回傳function pointer最大不同處在於
    lambda所回傳的function是保留的當時計算的環境(Closure)

    再仔細看看也就是C++中很常用的functor,
    只是lambda用更簡單的方式表達了這概念。

    如果再回頭看SICP第二、三章,就會發現用Closure是可以實作出一個OO的系統,然後瞭解OO中最核心的概念

    回覆刪除
  2. 一語驚醒夢中人, sicp 其實還有很多我還沒看懂, 感謝提點。

    回覆刪除

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

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