3
votes

I'm kinda new to Lua (not really done much with it yet) and I'm trying to wrap my mind around metatables. I have had them working before but now (after a number of months) I have encountered something really weird.

What should this script print when run?

__mt = {}

__mt.__index = function(table, key)
    print("In __index")
    return 99
end

test = {}
test.x = 5

setmetatable(test, __mt)

print(test.x)

Personally, I would expect it to print "In __index" (from the metamethod) followed by 99. However, whenever I run it I get 5. Nothing I do can get the index metamethod to run. It just acts like I'm using rawget() instead.

Curiously, adding

print(getmetatable(test).__index(test, "x"))

will do the right thing. The metatable is there, __index() is correct, it just isn't being called.

Is this a bug or am I just doing something stupid? I can't tell.

1

1 Answers

8
votes

The metamethod (in old terminology also called fallback) called __index is only called if the key x does not exist in the table, when you access t.x. Try print(t.y) instead!

Added: Yes, using a proxy table.

function doubletable(T)
  local store = T or {}
  local mt = {}
  mt.__index = function (t, k) return store[k] and 2*store[k] end
  mt.__newindex = store
  return setmetatable({}, mt)
end

t = doubletable({a=1, b=3})
t.c = 7
print(t.a, t.b, t.c)
-- output: 2    6   14