与封闭有关的资源?

时间:2011-11-14 05:59:12

标签: closures ml

我正在上一个使用ML的课程,我们正在讨论闭包,但我不太了解它们,特别是在ML中。我在课堂上做了笔记,对我来说没有多大意义/提供足够的细节。我试着在网上寻找更多信息,但找不到任何信息。

有没有人知道任何关于ML(或一般ML /闭包)关闭的资源是非常好的?

或者,如果有人可以发表一些关于如何在ML中实现闭包的一般想法/解释,或者ML中的闭包是什么样的,闭包是什么,等等。我真的很感激。我只是想了解闭包的概念/用法。

提前致谢!

2 个答案:

答案 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。现在,让我们重命名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.

所以 - 当一个函数有一个“自由变量”时,会为该函数创建一个闭包,它将“关闭”自由变量并在函数的生命周期内保留它。这样,当函数被传递并离开它所定义的上下文时,“自由变量”继续有效。

答案 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进行编译”等。