程式語言導論/閉包
外觀
< 程式語言導論

一個閉包 是一個函式的實現,以及一個將值繫結到函式體中出現的自由變數的表。一個變數 *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;
}