さて、次はクロージャと高階関数を組み合わせてみましょう。
クロージャと高階関数についても組み合わせて考えることは簡単です。
クロージャは引数以外の変数を実行時の環境ではなく、自身が定義された環境(静的スコープ)において解決することを特徴とするでした。 つまり関数内のローカル変数の状態が保存されました。
このクロージャと高階関数を組み合わせると、関数内のローカル変数を操作する関数をその関数の外の関数型の変数から呼び出せるようになります。
次の例を見てください。
// sample program for enhanced PL/0
var INC:func, DEC:func, DOUBLE:func, PR:func;
int: function counter();
begin
var n:int;
int: function Inc();
begin
n = n + 1;
print n;
end
int: function Dec();
begin
n = n - 1;
print n;
end
int: function Double();
begin
n = n * 2;
print n;
end
int: function Pr();
begin
print n;
end
n = 0;
INC = Inc;
DEC = Dec;
DOUBLE = Double;
PR = Pr;
end
begin
counter();
PR();
INC();
INC();
INC();
INC();
INC();
INC();
INC();
DEC();
DEC();
DEC();
INC();
INC();
DOUBLE();
PR();
end
関数counterの中で、変数nとInc, Dec, Double, Pr関数をローカル関数として定義しています。 そして、変数nは0に、外部の変数INCに関数Inc, 変数DECに関数Dec、変数DOUBLEに関数Double、および変数PRに関数Prを設定しています。
これにより、変数nは関数counter内のクロージャ変数となります。
変数INC、DEC、DOUBLE、PRには、関数counter内のローカル定義関数が高階関数として設定され、counter関数の外からも関数として呼び出されるようになります。
このようにクロージャと高階関数と組み合わせるとあたかも関数をオブジェクト指向のオブジェクトのように扱うことができるようになるのです。