Menu
Coddy logo textTech

クロージャとは?

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())  -- 出力: 3

createCounter() が呼び出されると、ローカル変数 count を作成し、匿名関数を返します。通常、createCounter() が終了すると count は消滅すると予想されます。しかし、返された関数は依然として count にアクセスできます。つまり、その変数を「クロージャとして取り込み(closes over)」ます。

counter() を呼び出すたびに、createCounter() が最初に実行されたときに作成されたのと同じ count 変数にアクセスして変更します。内部関数はその環境を保持し、呼び出し間で状態を維持します。

challenge icon

チャレンジ

簡単

特定の係数を持つ乗算関数を作成し、それを使用して直ちに指定された数値を乗算する関数 createMultiplier を作成してください。

ロジック:

  • createMultiplier の内部に、数値のパラメータを受け取るネストされた関数を作成します
  • ネストされた関数は、そのパラメータに外部関数の factor を乗算する必要があります
  • ネストされた関数はクロージャを形成し、factor の値を保持します
  • number パラメータを使用して乗算関数を呼び出し、その結果を返します

パラメータ:

  • factor (数値): 乗算する係数
  • number (数値): 乗算される数値

戻り値:

  • numberfactor を掛けた結果 (数値)

チートシート

クロージャは、入れ子になった関数が、外側の関数が実行を終了した後でも、その外側の関数のローカル変数を「記憶」しているときに発生します。

内側の関数はその環境を保持し、呼び出しの間で状態を維持します:

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())  -- 出力: 3

createCounter() が呼び出されると、ローカル変数 count を作成し、無名関数を返します。返された関数は依然として count にアクセスできます。つまり、外側の関数が実行を終了した後でも、その変数を「クロージャとして取り込み(closes over)」ます。

自分で試してみよう

function createMultiplier(factor, number)
    local multiply = function(x)
        return x * factor
    end
    
    -- 以下でmultiply関数を使用します

end
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

Logic & Flowのすべてのレッスン