2010-09-10 126 views
7

我想我明白爲什麼在使用動態範圍的語言中允許閉包時存在危險。也就是說,你似乎可以關閉變量OK,但是當試圖讀取它時,你將只能得到全局堆棧頂部的值。如果其他功能在此期間使用相同的名稱,這可能會很危險。關閉和動態範圍?

我錯過了其他一些微妙之處嗎?

回答

6

是的,這是基本問題。術語「封閉」是「詞彙封閉」的縮寫,儘管如此,by definition captures its lexical scope。我會用動態範圍的語言來調用東西,比如LAMBDA。只要你不嘗試返回它們,Lambdas在動態範圍的語言中是完全安全的。

(對於一個有趣的想法的實驗中,比較在Emacs Lisp的動態範圍化的λ返回到返回到在C堆棧分配變量的引用的問題的問題,並且兩者是如何在方案是不可能的。)

很久以前,當動態範圍的語言比今天少得多時,這就是所謂的funargs problem。你提到的問題是向上的funargs問題。

+3

我不會編輯答案,但:「通常」是錯誤的 - 閉包始終是「詞法閉包」,因爲它們通過它的方式關閉表達式詞彙環境。至於lambda是安全的 - 不能使用lambdas作爲封閉會極大地削弱它們的價值,但即使沒有這樣做,動態範圍對於您的程序的健康本質上是不利的,因爲您無法確定任何綁定的含義。 – 2010-09-10 02:32:30

+0

謝謝你的funargs鏈接。我從來沒有學過這個。 – 2010-09-10 03:05:39

+0

@Eli Barzilay:你說的對,我太過分了。我會刪除'通常'。至於一般的健康方案,我完全同意,但問題不是一般的。就像我所說的那樣,動態範圍的lambdas與無限制的指針一樣安全...... – 2010-09-11 17:52:48

7

我意識到我已經晚了幾年回答了這個問題,但我只是在做網絡搜索時碰到了這個問題,我想糾正一些發佈在這裏的錯誤信息。

「Closure」只是一個可調用對象,它包含代碼和一個爲該代碼中的自由變量提供綁定的環境。這種環境通常是一個詞彙環境,但沒有技術上的原因,爲什麼它不能成爲一個動態環境。

訣竅是關閉環境代碼而不是特定的值。這就是Lisp 1.5所做的,也是MACLisp爲「向下的樂趣」所做的。

您可以在http://www.softwarepreservation.org/projects/LISP/book

看到Lisp的1.5做這個通過閱讀Lisp的1.5手動特別注意在附錄B中的eval如何處理功能,以及如何運用手柄FUNARG。

您可以從http://c2.com/cgi/wiki?DynamicClosure

獲得使用動態關閉編程的基本味道,您可以深入地介紹從ftp://publications.ai.mit.edu/ai-publications/pdf/AIM-199.pdf

現代動態範圍的語言一般採用淺的結合,在當前得到的執行問題每個變量的值保存在一個全局位置,函數調用將舊值保存在堆棧中。 http://www.pipeline.com/~hbaker1/ShallowBinding.html

+0

我意識到我可能會晚幾年問這個問題:P,但是你介意解釋什麼是'make-adder','addx'和'do-test'形成這個[link](http: //wiki.c2.com/?DynamicClosure)你引用了嗎?從Lisp 1.5手冊來講,它們不是函數閉包,但是用'lambda'定義。它們看起來更像宏,用單純的表達式代替(即沒有關聯環境)。 – wlnirvana 2017-06-22 06:06:53

+0

他們只是正常的,動態範圍的功能。被調用時,他們可以訪問動態範圍內的變量。該程序中唯一的關閉/ funarg是由FUNCTION創建的。 – Glomek 2017-07-14 18:01:20

+0

好的,也許這只是一個術語問題,但我更願意說沒有這種叫做「動態封閉」的東西(我個人認爲這比混淆不清)。引用的AIM-199.pdf文件實際上給出了單詞閉包的來源,這表明它首先僅用於「閉合」lambda表達式。動態範圍的函數,其自由變量逃避到當前的運行時環境,在這個意義上沒有關閉,因此在該論文中被稱爲「打開lambda表達式」。 – wlnirvana 2017-07-21 01:59:11