クロージャとは?
CoddyのLuaジャーニー「Logic & Flow」セクションの一部 — レッスン 14/54。
関数を変数に格納したり、引数として渡したり、他の関数から返したりできることを学びました。ここからは、これによってもたらされる最も強力な結果の1つであるクロージャについて探求していきます。
クロージャは、入れ子になった関数が、それを取り囲む関数(外側の関数)の実行が終了した後でも、その関数のローカル変数を「覚えている」ときに発生します。最初は奇妙に聞こえるかもしれません。それを作成した関数の処理が終わった後、どうして変数が存在し続けられるのでしょうか?
この概念を説明する簡単な例を次に示します。
function createCounter()
local count = 0
return function()
count = count + 1
return count
end
end
local counter = createCounter()
print(counter()) -- 出力: 1
print(counter()) -- 出力: 2
print(counter()) -- 出力: 3createCounter() が呼び出されると、ローカル変数 count を作成し、匿名関数を返します。通常、createCounter() が終了すると count は消滅すると予想されます。しかし、返された関数は依然として count にアクセスできます。つまり、その変数を「クロージャとして取り込み(closes over)」ます。
counter() を呼び出すたびに、createCounter() が最初に実行されたときに作成されたのと同じ count 変数にアクセスして変更します。内部関数はその環境を保持し、呼び出し間で状態を維持します。
チャレンジ
簡単特定の係数を持つ乗算関数を作成し、それを使用して直ちに指定された数値を乗算する関数 createMultiplier を作成してください。
ロジック:
createMultiplierの内部に、数値のパラメータを受け取るネストされた関数を作成します- ネストされた関数は、そのパラメータに外部関数の
factorを乗算する必要があります - ネストされた関数はクロージャを形成し、
factorの値を保持します numberパラメータを使用して乗算関数を呼び出し、その結果を返します
パラメータ:
factor(数値): 乗算する係数number(数値): 乗算される数値
戻り値:
numberにfactorを掛けた結果 (数値)
チートシート
クロージャは、入れ子になった関数が、外側の関数が実行を終了した後でも、その外側の関数のローカル変数を「記憶」しているときに発生します。
内側の関数はその環境を保持し、呼び出しの間で状態を維持します:
function createCounter()
local count = 0
return function()
count = count + 1
return count
end
end
local counter = createCounter()
print(counter()) -- 出力: 1
print(counter()) -- 出力: 2
print(counter()) -- 出力: 3createCounter() が呼び出されると、ローカル変数 count を作成し、無名関数を返します。返された関数は依然として count にアクセスできます。つまり、外側の関数が実行を終了した後でも、その変数を「クロージャとして取り込み(closes over)」ます。
自分で試してみよう
function createMultiplier(factor, number)
local multiply = function(x)
return x * factor
end
-- 以下でmultiply関数を使用します
endこのレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。