我正在參加一個使用ML的課程,我們將討論閉包,但我不太瞭解它們,特別是在ML中。我在課堂上記筆記,他們對我沒有多大意義/提供足夠的細節。我試着在網上尋找更多的信息,但找不到任何。與ML關閉相關的資源?
有沒有人知道任何資源關於關閉在ML(或關於ML /關閉一般)是非常好的?
或者,如果有人可以發表一些關於如何在ML中實現閉包的一般想法/解釋或ML中的閉包如何看起來像什麼封閉等等,我真的很感激它。我只是想了解關閉的概念/使用。
在此先感謝!
我正在參加一個使用ML的課程,我們將討論閉包,但我不太瞭解它們,特別是在ML中。我在課堂上記筆記,他們對我沒有多大意義/提供足夠的細節。我試着在網上尋找更多的信息,但找不到任何。與ML關閉相關的資源?
有沒有人知道任何資源關於關閉在ML(或關於ML /關閉一般)是非常好的?
或者,如果有人可以發表一些關於如何在ML中實現閉包的一般想法/解釋或ML中的閉包如何看起來像什麼封閉等等,我真的很感激它。我只是想了解關閉的概念/使用。
在此先感謝!
關閉是意思是在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的,或阿佩爾的書「與延續編譯」,等等
我不知道任何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
。現在,讓我們重命名foo
和bar
明白爲什麼這是有用的:
(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.
所以 - 當一個函數有一個「自由變量」,一個封閉的爲「關閉」自由變量的函數創建,並在函數的整個生命週期內保留它。這樣,當函數傳遞並離開它定義的上下文時,「自由變量」繼續有效。