Shared Upvalues Between Closures
Multiple closures sharing the same upvalue and mutation implications.
Shared Upvalues Between Closures is a free Lua Academy lesson on CoddyKit. This is lesson 2 of 4. Any 3 lessons of this learning path are free to read in full — after that, CoddyKit PRO unlocks every lesson, plus hands-on practice with a built-in code editor and a 24/7 AI tutor. It is part of the Lua Academy learning path, and your progress syncs across the web and the CoddyKit app. The Lua Academy course includes 4 lessons in total.
Sharing the Same Upvalue
Two closures defined in the same scope can share the exact same upvalue cell. Mutations by one are seen by the other.
local function makeGetterSetter()
local value = 0
local function get() return value end
local function set(v) value = v end
return get, set
end
local get, set = makeGetterSetter()
set(42)
print(get()) -- 42Why Sharing Happens
Lua does not copy upvalues per closure. All closures created in the same block pointing to the same local variable share one upvalue cell.
Observer Pattern via Shared Upvalue
A shared upvalue can act as a message bus between multiple closures.
local count = 0
local inc = function() count = count + 1 end
local dec = function() count = count - 1 end
local get = function() return count end
inc(); inc(); dec()
print(get()) -- 1Loop Variable Gotcha
In a numeric for loop, each iteration creates a new local loop variable, so closures capture independent upvalues.
local fns = {}
for i = 1, 3 do
fns[i] = function() return i end
end
print(fns[1](), fns[2](), fns[3]()) -- 1 2 3 (each closure has its own i)while Loop Variable Gotcha
In a while loop, if you close over a single variable that changes, all closures share the same upvalue and see the final value.
local fns = {}
local i = 0
while i < 3 do
i = i + 1
fns[i] = function() return i end -- all share same i!
end
print(fns[1]()) -- 3 (not 1!)Capturing a New Local
To capture independent values in a while loop, introduce a new local inside the loop body.
local fns = {}
local i = 0
while i < 3 do
i = i + 1
local ci = i -- new local per iteration
fns[i] = function() return ci end
end
print(fns[1]()) -- 1, fns[2]() == 2Shared State Module Pattern
A module can expose multiple functions sharing a private state table through upvalues.
local function makeStack()
local data = {}
return {
push = function(v) data[#data+1] = v end,
pop = function() local v = data[#data]; data[#data]=nil; return v end,
size = function() return #data end,
}
endAliasing and Mutation
Be careful: all closures referencing the same upvalue see the same mutation immediately. This is powerful but can cause unintended coupling.
Upvalue Identity
debug.upvalueid(f, n) returns the unique identity of the nth upvalue of function f. Two closures with the same upvalue ID share the same cell.
debug.upvaluejoin
debug.upvaluejoin(f1, n1, f2, n2) makes the n1-th upvalue of f1 share the same cell as the n2-th upvalue of f2. A low-level tool for debugging.
Practical Patterns
- Getter/setter pairs sharing a private variable.
- Event counter with reset exposed via multiple closures.
- Module state shared across several API functions.
Shared Upvalue Question
Two closures get and set are created in the same scope, both capturing value. If set(99) is called, what does get() return?
Recap: Shared Upvalues
Closures in the same scope share upvalue cells. Mutations are immediately visible to all sharing closures. This is the foundation of encapsulation and module state in Lua.
Learn Lua with an AI tutor — free
Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.
- Courses
- 40
- Lessons
- 159
Frequently Asked Questions
Is the “Shared Upvalues Between Closures” lesson free?
Yes — any 3 lessons of the Lua Academy learning path, including “Shared Upvalues Between Closures”, are free to read in full here on the web. After that, CoddyKit PRO unlocks every lesson, plus interactive practice with a built-in code editor and a 24/7 AI tutor. The Lua Academy course includes 4 lessons in total.
What will I learn in “Shared Upvalues Between Closures”?
Multiple closures sharing the same upvalue and mutation implications. You practise Lua Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Lua Academy?
No prior experience is required. Lua Academy on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 2 of 4.
How long does the “Shared Upvalues Between Closures” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Lua Academy lesson?
Yes. Every Lua Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- What Are Upvalues?
- Shared Upvalues Between Closures
- Factory Functions and Generators
- Memoization with Closures