🎓 A1Learner
🔍
0 of 52 lessons completed

Lua Metamethod __newindex

The __newindex metamethod intercepts a write to a missing key. It runs only when the key has no value stored in the table itself.

A storage table receives a new write

A write to a new key goes to the storage table. Reading the original table still gives nil for that key.

local store = {}
local t = {}
setmetatable(t, {__newindex = store})
t.score = 10
print(store.score, t.score)

A guard function can reject a bad write

A guard function stores a score only when it is zero or more. A negative score is ignored, and a later good score is stored.

local function guard(t, k, v)
  if k == "score" and v >= 0 then
    rawset(t, k, v)
  end
end
local t = {}
setmetatable(t, {__newindex = guard})
t.score = -5
print(t.score)
t.score = 20
print(t.score)

A stored key bypasses the intercept

A write to a stored count changes the table itself. A write to a new key goes to the log table instead.

local log = {}
local t = {count = 1}
setmetatable(t, {__newindex = function(t, k, v)
  log[k] = v
end})
t.count = 99
t.extra = 7
print(t.count, log.count, log.extra)

Example

local function guard(t, k, v)
  if k == "volume" then
    if v >= 0 and v <= 10 then
      rawset(t, k, v)
    end
  else
    rawset(t, k, v)
  end
end
local s = {}
setmetatable(s, {__newindex = guard})
s.volume = 15
print(s.volume)
s.volume = 8
print(s.volume)
s.title = "Hi"
print(s.title)

Key points

  • Missing key: a key with no value stored in the table itself.
  • Intercept: a __newindex field takes over the write instead of storing it in the table.
  • Table form: a table stored as __newindex receives the write for a missing key.
  • Function form: a function stored as __newindex is called with the table, the key, and the new value.
  • Stored key: a write to a key already stored in the table bypasses __newindex completely.

In this example, a settings table starts empty. A volume of fifteen is outside the allowed range, so it is ignored. A volume of eight is inside the range, so it is stored, and a new title is stored as well.

Note

reading a redirected key still gives nil unless a matching fallback supplies it.

Try it Yourself

Edit the code, then press Run.

Running is simulated

Exercise

A table has a storage table as its __newindex field. A write to a new key goes where?