我正在上一个使用ML的课程,我们正在讨论闭包,但我不太了解它们,特别是在ML中。我在课堂上做了笔记,对我来说没有多大意义/提供足够的细节。我试着在网上寻找更多信息,但找不到任何信息。
有没有人知道任何关于ML(或一般ML /闭包)关闭的资源是非常好的?
或者,如果有人可以发表一些关于如何在ML中实现闭包的一般想法/解释,或者ML中的闭包是什么样的,闭包是什么,等等。我真的很感激。我只是想了解闭包的概念/用法。
提前致谢!
答案 0 :(得分: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
时,我们的意思是什么? foo中未定义a
,因此称为自由变量。要了解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
的含义。 Scheme(以及ML)是 lexically-scoped ,这意味着要找出变量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
需要坚持一段时间。这就是闭包的来源。a
的值是“关闭”,所以只要函数foo
存在,它就会一直存在。这样,即使foo
完成执行,我们也可以调用bar
。现在,让我们重命名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.
所以 - 当一个函数有一个“自由变量”时,会为该函数创建一个闭包,它将“关闭”自由变量并在函数的生命周期内保留它。这样,当函数被传递并离开它所定义的上下文时,“自由变量”继续有效。
答案 1 :(得分: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.因此它混合了代码和&amp;闭包中的数据(闭环变量的环境)。
阅读更多维基百科在closure上的条目,以及任何优秀的教科书:SICP(由Sussman撰写),或小篇章中的C.Queinnec Lisp,或任何关于Ocaml的优秀入门书,或Appel的书“使用Continuations进行编译”等。