Lua Closures with State
A closure with state is a function returned by another function that keeps its own local variables alive after the outer call ends. Each returned function has its own set of those variables.
A returned function keeps its count
The factory makes a counter. Each call moves the count by one.
local function make_counter()
local count = 0
return function()
count = count + 1
return count
end
end
local count_up = make_counter()
print(count_up())
print(count_up())
print(count_up())Two counters do not share state
Two calls to the factory make two counters. Their counts move on their own.
local function make_counter()
local count = 0
return function()
count = count + 1
return count
end
end
local a = make_counter()
local b = make_counter()
print(a())
print(a())
print(b())
print(a())A factory argument sets the start
The factory can take a start value. The first call then adds one to that start.
local function make_counter(start)
local count = start
return function()
count = count + 1
return count
end
end
local count_from_ten = make_counter(10)
print(count_from_ten())
print(count_from_ten())
local count_from_hundred = make_counter(100)
print(count_from_hundred())Example
local function make_counter(start, step)
local count = start
return function()
count = count + step
return count
end
end
local a = make_counter(0, 2)
local b = make_counter(10, 5)
print(a())
print(a())
print(b())
print(a())
print(b())Key points
- Upvalue: a local variable from an outer function that an inner function keeps using.
- Factory: a function that builds and returns a new function each time it runs.
- Fresh state: each call to a factory gives the new function its own separate variables.
- Counter step: calling the returned function changes only its own stored count.
- Start value: a factory argument that sets the first value of the new state.
In this example, the factory takes a start value and a step value and returns a function that adds the step to its own count. Counter a starts at 0 and steps by 2, while counter b starts at 10 and steps by 5. The prints show a at 2 and 4, then b at 15, then a again at 6, then b at 20, so each counter keeps its own state.
Note
Lua functions are values, so a factory can return a function just like it returns a number.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
A factory makes a counter that starts at 0 and adds 1 on each call. You make counter a, call it twice, then make counter b and call it once. What does the call to b return?