2011-11-14 183 views
0

我正在參加一個使用ML的課程,我們將討論閉包,但我不太瞭解它們,特別是在ML中。我在課堂上記筆記,他們對我沒有多大意義/提供足夠的細節。我試着在網上尋找更多的信息,但找不到任何。與ML關閉相關的資源?

有沒有人知道任何資源關於關閉在ML(或關於ML /關閉一般)是非常好的?

或者,如果有人可以發表一些關於如何在ML中實現閉包的一般想法/解釋或ML中的閉包如何看起來像什麼封閉等等,我真的很感激它。我只是想了解關閉的概念/使用。

在此先感謝!

回答

0

關閉是意思是在ML(或在Ocaml,Scheme,Lisp中)來實現函數。所以所有的函數都是閉包(也就是代碼和數據的混合)。例如(使用ocaml的語法)

(* function making an incrementer, returning a function *) 
let make_incr i = fun x -> x + i;; 

(* use it to define the successor function *) 
let succ = make_incr 1;; 

(* compute the successor of 4 *) 
succ 4;; 

OCaml的解釋當然是成功回答

val make_incr : int -> int -> int = <fun> 
val succ : int -> int = <fun> 
- : int = 5 

你看到make_incr是高階功能:給某個整數它會產生一個新的功能。因此給定1,它在上面的例子中產生succ。並且succ包含加法代碼和整數1.因此它將代碼&數據(封閉變量的環境)混合在閉包中。

閱讀維基百科對closure條目,任何好的教科書:在SICP(由蘇斯曼),或C.Queinnec Lisp的小件,或任何不錯的入門書ocaml的,或阿佩爾的書「與延續編譯」,等等

1

我不知道任何ML,所以我的答案將在Scheme中,這是另一種函數式編程語言。我假設你不知道Scheme,並會很好地評論我的代碼。

**注意:Scheme是動態類型的,所以你不會看到任何類型的聲明(如int,float,char等)。

(define (double x)  ;this defines a new function called "double" which takes one argument called x 
    (* 2 x))    ;return 2 times its argument. Function application in Scheme takes the form (function arg1 arg2 ...) 

我們將使用這個新定義函數是這樣的:

(double 10) ;returns 20 
(double 8) ;returns 16 

在這個函數,變量x局部變量x是double的形式參數。無論何時我們在雙重身體中使用x,毫無疑問我們的意思是什麼。但這又如何:

(define (foo x)   ;define a function "foo" which takes on argument called x 
    (* x a))    ;return x times a 

再一次,x是一個形式參數。但是a呢?當我們在foo的主體中使用a時,我們的意思是什麼? a未在foo中定義,所以它被稱爲自由變量。要看a的含義,我們必須看看foo以外的東西。例如,假設FOO在此背景下定義:

(define (bar a)  ;define a function "bar" which takes one argument called "a" 
    (define (foo x)  ;define "foo" as an inner function of bar 
     (* x a)))  ;foo returns x * a 

現在我們知道什麼a手段。計劃(也ML)是詞法作用域,這意味着找出變量a手段,我們看一下原文上下文(希望這是有道理的)。

現在,bar的上述定義實際上是不正確的:即使認爲foo返回某些內容,bar也不會返回任何內容。它將foo定義爲內部函數,但在該定義之後沒有語句。讓我們來解決這個問題:

(define (bar a)  ;define a function "bar" which takes one argument called "a" 
    (define (foo x)  ;define "foo" as an inner function of bar 
     (* x a))   ;foo returns x * a 
    foo)    ;bar returns the function foo 

現在,bar返回函數foo。我們剛剛將bar轉換爲高階函數,因爲它返回另一個函數。

但是有一個問題。通常,當bar返回時,不再需要本地變量a,並且其值會丟失。但foo仍然引用a!所以a需要堅持一段時間。這是關閉的地方.的值是「關閉」,因此只要功能foo存在,它就會持續存在。這樣,即使在bar執行完畢後,我們也可以撥打foo。現在,讓我們重命名foobar明白爲什麼這是有用的:

(define (make-multiplier a) 
    (define (multiplier x) 
     (* x a)) 
    multiplier) 

現在,我們可以這樣做:

(define triple (make-multiplier 3)) ;call make-multiplier with the value 3. Bind the function which is returned to the variable "triple." 
(triple 5)       ;call triple with the value 5. Since the 3 was "closed over", (triple 5) returns 5 * 3, which is 15. 

所以 - 當一個函數有一個「自由變量」,一個封閉的爲「關閉」自由變量的函數創建,並在函數的整個生命週期內保留它。這樣,當函數傳遞並離開它定義的上下文時,「自由變量」繼續有效。