编程语言导论/闭包
外观
< 编程语言导论
一个闭包 是一个函数的实现,以及一个将值绑定到函数体中出现的自由变量的表。一个变量 *v* 在函数体 *f* 中是自由的,如果 *v* 在 *f* 内部使用,但没有在 *f* 中声明。闭包为开发者提供了一种将函数传递出去的方式,以及关于这些函数创建上下文的某些信息。从实际的角度来看,闭包允许开发者编写*函数工厂*。例如,下面我们有一个 Python 函数,它产生一元求和
def unarySumFactory(a):
def unarySum(b): return a + b
return unarySum
inc = unarySumFactory(1)
print inc(2)
sum2 = unarySumFactory(2)
print sum2(2)
在上面的例子中,我们注意到变量 *a* 在函数 unarySum
的主体中是自由的。这个变量在函数 unarySumFactory
的作用域中声明,并且它可以在 unarySum
内部引用这一事实为语言设计者提出了一个实现问题。通常,一旦函数返回它的值,为它的激活记录保留的空间就会被释放。但是,如果这个空间被释放,我们例子中的变量 *a* 一旦 unarySumFactory
返回一个值,就将不再有存储位置。为了绕过这个困难,闭包被实现为一对 *(f,t)*,其中 *f* 是指向函数实现的指针,*t* 是指向一个表,该表包含与值关联的所有在 *f* 中使用的自由变量。
因为闭包可能比创建它的函数存活更久,所以通常 *(f,t)* 这对,以及表 *t* 的内容会在堆中分配。下面的代码是用 C 写的,实现了之前看到的 unarySumFactory
调用。C 没有语法支持闭包。但是,我们可以通过将高阶函数调用与动态堆分配结合起来来实现闭包。
#include <stdio.h>
#include <stdlib.h>
typedef struct struct_free_variables_unarySum {
int x;
} FREE_VARIABLES_unarySum;
typedef struct {
FREE_VARIABLES_unarySum* t;
int (*f)(FREE_VARIABLES_unarySum* t, int x);
} CLOSURE_unarySum;
int unarySum(FREE_VARIABLES_unarySum* t, int y) {
return y + t->x;
};
void* unarySumFactory(int x) {
CLOSURE_unarySum* c = (CLOSURE_unarySum*) malloc (sizeof(CLOSURE_unarySum));
c->t = (FREE_VARIABLES_unarySum*) malloc (sizeof(FREE_VARIABLES_unarySum));
c->t->x = x;
c->f = &unarySum;
return c;
}
int test(int n) {
CLOSURE_unarySum* c = unarySumFactory(2);
int retVal = c->f(c->t, n);
free(c->t);
free(c);
return retVal;
}
int main(int argc, char** argv) {
printf("%d\n", test(argc));
return 0;
}