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?