I'd like to have a write-once table in Lua (specifically LuaJIT 2.0.3), so that:
local tbl = write_once_tbl()
tbl["a"] = 'foo'
tbl["b"] = 'bar'
tbl["a"] = 'baz' -- asserts false
Ideally, this would otherwise function like a regular table (pairs() and ipairs() work).
__newindex is basically the opposite of what I'd want for implementing this easily, and I am unaware of any techniques for making a proxy table pattern work with pairs() and ipairs().
You need to use a proxy table, that is, an empty table that catches all access to the actual table:
function write_once_tbl()
local T={}
return setmetatable({},{
__index=T,
__newindex=
function (t,k,v)
if T[k]==nil then
T[k]=v
else
error("table is write-once")
end
end,
__pairs= function (t) return pairs(T) end,
__ipairs= function (t) return ipairs(T) end,
})
end
Note that __pairs
and __ipairs
only work from Lua 5.2 onwards.