2011-11-14 71 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. 

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