0Pricing
Lua Academy · Lesson

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 — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Lua Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

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())  -- 42

Why 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())  -- 1

Loop 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]() == 2

Shared 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,
  }
end

Aliasing 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.

Frequently asked questions

Is the “Shared Upvalues Between Closures” lesson free?

Yes — the full text of “Shared Upvalues Between Closures” is free to read here on the web, and the Lua Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Lua Academy course, upgrade to CoddyKit PRO.

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; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.

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

  1. What Are Upvalues?
  2. Shared Upvalues Between Closures
  3. Factory Functions and Generators
  4. Memoization with Closures
← Back to Lua Academy