🎓 A1Learner
🔍
0 of 49 lessons completed

Lua To-Be-Closed Variables

A to-be-closed variable is a local variable that Lua closes on its own when its scope ends. The <close> mark tells Lua to run the value's __close metamethod at that moment.

The close runs when the scope ends

The log is empty inside the scope and holds one entry after it.

local log = {}
local function mk(name)
  return setmetatable({name = name}, {__close = function(v) log[#log + 1] = v.name end})
end
do
  local r <close> = mk("door")
  print(#log)
end
print(#log)
print(log[1])

__close receives the value and the error

On a clean exit the error is nil.

local log = {}
local function mk(name)
  return setmetatable({name = name}, {__close = function(v, err) log[#log + 1] = v.name .. ":" .. tostring(err) end})
end
do
  local r <close> = mk("lamp")
end
print(log[1])

A value without __close raises an error

The guarded call reports failure.

local ok = pcall(function()
  local x <close> = 42
end)
print(ok)

Example

local log = {}
local function mk(name)
  return setmetatable({name = name}, {__close = function(v, err) log[#log + 1] = v.name .. ":" .. tostring(err) end})
end
do
  local a <close> = mk("tap")
end
do
  local b <close> = mk("light")
end
print(table.concat(log, ","))

Key points

  • To-be-closed variable: a local marked <close> that Lua closes when its scope ends.
  • __close metamethod: a function Lua calls on the value when the scope ends.
  • Close arguments: __close receives the value itself and an error value.
  • Clean exit: the error value is nil when the scope ends without an error.
  • Non-closable value: a value without a __close metamethod makes Lua raise an error when the scope ends.

In this example, the first scope opens a tap and closes it at the scope end. The second scope opens a light and closes it the same way. The log lists both closes in scope order.

Note

a <close> variable holding nil closes silently, with no call and no error.

Try it Yourself

Edit the code, then press Run.

Running is simulated

Exercise

When does Lua call a value's __close metamethod?