LUA / CHAPTER 12

Intercepting writes and raw operations

Advanced

Understand when metatable hooks do and do not run.

By the end of this chapter

  • Explain __newindex for absent keys
  • Use rawget and rawset deliberately
  • Build validation around a backing store

The idea

A table’s __newindex hook is consulted when assigning a key that is not already present in the table. It is not a universal observer for every assignment. Updating an existing ordinary field bypasses that hook. Raw operations intentionally bypass the relevant metatable behavior and are useful inside a hook when the implementation needs to access actual storage without recursion.

To validate every write through an interface, a proxy table can keep its public raw storage empty and delegate values to a separate backing table. Reads use __index and writes use __newindex, allowing checks before the backing store changes. This is an API convention rather than an absolute security boundary if callers can reach the backing data or use raw operations on the proxy.

Lua example
local writes=0
local t=setmetatable({}, {__newindex=function(self,k,v)
  writes=writes+1
  rawset(self,k,v)
end})
t.x=1
t.x=2
print(writes)
print(t.x)
Result
1
2

Only the first assignment targets an absent raw key. After rawset creates x, the later ordinary update bypasses __newindex.

Try it yourself

Implement a proxy that rejects negative assigned counts while keeping its backing table private.

Use your own editor for this exercise. Runnable challenges on CodeQuest are available for JavaScript, Python, and SQL.

CHECK YOUR UNDERSTANDING

Chapter checkpoint

Why use rawset inside a __newindex hook that stores the new field?