0

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

有谁知道任何关于 ML 中的闭包(或关于 ML / 闭包)非常好的资源?

或者,如果有人可以就如何在 ML 中实现闭包或 ML 中的闭包是什么样子、闭包是什么等发表一些一般性的想法/解释,我将非常感激。我只是想了解闭包的概念/使用。

提前致谢!

4

2 回答 2

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在 double 的主体中使用时,毫无疑问我们所指的值是什么。但是这个呢:

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

再次,x是一个形式参数。但是呢aa当我们在 foo 的主体中使用时,我们的意思是什么?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意思了。Scheme(以及 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局部变量,并且它的值会丢失。afoo仍然参考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.

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

于 2011-11-17T02:25:34.607 回答
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。因此它将代码和数据(封闭变量的环境)混合在一个闭包中。

阅读更多 Wikipedia 关于closure的条目,以及任何好的教科书:SICP(Sussman 撰写)或 C.Queinnec Lisp in Small Pieces,或任何关于 Ocaml 的好的介绍性书籍,或 Appel 的书“Compiling with Continuations”等。

于 2011-11-14T06:26:00.923 回答