Reading — step 1 of 5
Learn
Lua closures capture upvalues by reference, not by copy. Multiple closures can share state.
local function makeCounter()
local count = 0
return function()
count = count + 1
return count
end
end
local c1 = makeCounter()
local c2 = makeCounter()
print(c1()) -- 1
print(c1()) -- 2
print(c2()) -- 1 — different instance
print(c1()) -- 3
Each call to makeCounter() creates a fresh count upvalue. Each returned closure has its own.
Sharing upvalues between multiple closures:
local function makeAccount(initial)
local balance = initial
return {
deposit = function(n) balance = balance + n end,
withdraw = function(n) balance = balance - n end,
balance = function() return balance end
}
end
local a = makeAccount(100)
a.deposit(50)
a.withdraw(20)
print(a.balance()) -- 130
The three closures share the same balance upvalue. This is how you do private state in Lua — encapsulation without classes.
Closures + tables = OO without metatables:
local function newPerson(name)
return {
getName = function() return name end,
setName = function(n) name = n end
}
end
The name field isn't on the table — it's an upvalue that the methods can access. External code can't see it without going through the methods.
debug.getupvalue / debug.setupvalue for introspection (and breaking encapsulation, naturally):
local name, value = debug.getupvalue(account.balance, 1)
print(name, value) -- "balance", 130
The debug library lets you inspect closures' captured state — useful for debugging, dangerous for security.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…