lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Alan Hightower wrote:

No, the second case is independent of the first.  When I perform
root.sub1.foo = bar, sub1 doesn't exist in the root yet
After the line executes, it does, yet I never get called  > for the new index add.  This seems broken to me.

It would be, but it demonstrably doesn't happen:

> function _proc_lua_assignment(t, k, v) print("Setting field "..k) end
> root = {}
> root._hidden_vals = {}
> root._my_meta = {}
> root._my_meta.__index = root._hidden_vals
> root._my_meta.__newindex = _proc_lua_assignment
> setmetatable (root, root._my_meta)
> root.sub1.foo = "bar"
stdin:1: attempt to index field 'sub1' (a nil value)
stack traceback:
        stdin:1: in main chunk
        [C]: ?
> root.sub1 = "bar"
Setting field sub1

---------------

When Lua evaluates root.sub1.foo = "bar", it will first evaluate root.sub1, which will trigger the __index metamethod of root. (If
it had one -- in your example, __index is just a table.) So you could
create the sub1 table in the __index metamethod.

That might or might not be the right thing to do, though: it might
be, for example, a typo in the config file. There are a couple of
ways of getting around that, though. One possibility is to never
actually store anything in root (or the "magic" subtables); rather,
store them in shadow tables accessed through the __index metamethod.
That will allow you to catch changes as well as new assignments,
which may be what you want to do.

By the way, it's not necessary (nor desirable, in most cases)
to store the metatable or the "hidden" values (which are
not very hidden :) ) in the table itself.

The metatable can be more easily accessed with
lua_getmetatable(); you can also use closure upvalues (in
the __index and __newindex functions) in order to hold
references to tables which you don't want to expose to
the Lua environment.