我正在参加一个使用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.
所以 - 当一个函数有一个“自由变量”,一个封闭的为“关闭”自由变量的函数创建,并在函数的整个生命周期内保留它。这样,当函数传递并离开它定义的上下文时,“自由变量”继续有效。