定義
閉包 (closure)是個精確但又很難解釋的電腦名詞。在 Perl 裡面,閉包是以 匿名函式的形式來實現,具有持續參照位於該函式範圍之外的文字式變數值的能力。 這些外部的文字變數會神奇地保留它們在閉包函式最初定義時的值 (深連結)。如果一個程式語言容許函式遞迴另一個函式的話 (像 Perl 就是),閉包便具有意 義。要注意的是,有些語言雖提供匿名函式的功能,但卻無法正確處理閉包; Python 這個語言便是一例。如果要想多了解閉包的話,建議你去找本功能性程式 設計的教科書來看。Scheme這個語言不僅支援閉包,更鼓勵多加使用。
函式
以下是個典型的產生函式的函式:sub add_function_generator {
return sub { shift + shift };
}
$add_sub = add_function_generator();
$sum = &$add_sub(4,5); # $sum現在是 9了
閉包用起來就像是個函式樣板,其中保留了一些可以在稍後再填入的空格。 add_function_generator() 所遞迴的匿名函式在技術上來講並不能算是一個閉包, 因為它沒有用到任何位在這個函式範圍之外的文字變數。
把上面這個例子和下面這個make_adder()函式對照一下,下面這個函式所遞迴的匿名函式中使用了一個外部的文字變數。這種指名外部函式的作法需要由 Perl遞迴一個適當的閉包,因此那個文字變數在匿名函式產生之時的值便永久地被鎖進閉 包里。
sub make_adder {
my $addpiece = shift;
return sub { shift + $addpiece };
}
$f1 = make_adder(20);
$f2 = make_adder(555);
這樣一來&$f1($n) 永遠會是 20加上你傳進去的值$n ,而&$f2($n) 將 永遠會是 555加上你傳進去的值$n。$addpiece的值會在閉包中保留下來。
閉包在比較實際的場合中也常用得到,譬如當你想把一些程式碼傳入一個函式時:
my $line;
timeout( 30, sub { $line = <STDIN> } );
如果要執行的程式碼當初是以字串的形式傳入的話,即'$line = <STDIN>' ,那麽timeout() 這個假想的函式在回到該函式被呼叫時所在的範圍後便無法再擷取$list這個文字變數的值了。