Closures
A closure is a function that remembers the local variables around it — even after the code that created them has finished.
local function makeCounter()
local count = 0
return function()
count = count + 1
return count
end
end
local c1 = makeCounter()
local c2 = makeCounter()
print(c1(), c1(), c1())
print(c2())
1 2 3
1
makeCounterreturns an inner function that usescount.- Each call to
makeCountercreates a newcount, soc1andc2have independent state. countis private: nothing outside can read or change it except through the returned function. (The captured variables are called upvalues in Lua.)
Configuring behavior
local function multiplier(factor)
return function(x) return x * factor end
end
local double, triple = multiplier(2), multiplier(3)
print(double(21), triple(7))
local function makeGreeter(greeting)
return function(name)
return greeting .. ", " .. name .. "!"
end
end
local hello = makeGreeter("Hello")
print(hello("Ada"))
42 21
Hello, Ada!
Closures in loops
Each loop iteration gets a fresh loop variable, so closures created in a loop capture different values:
local actions = {}
for i = 1, 3 do
actions[i] = function() return "action " .. i end
end
for _, action in ipairs(actions) do
print(action())
end
action 1
action 2
action 3
Callbacks
Closures are everywhere in Lua code: event handlers in games, key mappings in Neovim, and callbacks in servers all capture the state they need:
local handlers = {}
local function on(event, fn) handlers[event] = fn end
local function emit(event, ...) if handlers[event] then handlers[event](...) end end
local score = 0
on("coin", function(value) score = score + value end)
emit("coin", 10)
emit("coin", 5)
print("score: " .. score)
score: 15