[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: "nesting" metatables
- From: Marc Balmer <marc@...>
- Date: Thu, 24 Dec 2015 10:42:38 +0100
> Am 24.12.2015 um 10:29 schrieb Jonathan Goble <jcgoble3@gmail.com>:
>
> On Thu, Dec 24, 2015 at 4:15 AM, Marc Balmer <marc@msys.ch> wrote:
>> Is it possible to define a metatable that has a table of functions as the __index element, and then, trigger another metatable when a key is not found up in __index?
>
> Set a metatable for the table of functions, with __index set to your
> catch-all index function.
>
> In other words, if __index is a table, and that table doesn't contain
> the key, then Lua will check if that table has a metatable of its own
> with an __index metamethod. This metatable chaining could
> theoretically continue indefinitely.
>
Actually I found a nice way to achieve what I want. In the index function I first look for the special values, and if they are not there, I lookup the key in the metatable using rawget.
Works like a charm:
res = db:exec('select 'abc' as name')
print(res:ntuples()) -- outputs '1'
print(res[1].name) -- outputs 'abc'
Here's the function:
static int
res_index(lua_State *L)
{
if (lua_type(L, -1) == LUA_TNUMBER) {
tuple *t;
PGresult *res;
int row;
res = *(PGresult **)luaL_checkudata(L, 1, RES_METATABLE);
row = luaL_checkinteger(L, 2) - 1;
if (row < 0 || row > PQntuples(res))
lua_pushnil(L);
else {
t = lua_newuserdata(L, sizeof(tuple));
t->res = res;
t->row = row;
luaL_getmetatable(L, TUPLE_METATABLE);
lua_setmetatable(L, -2);
}
} else {
const char *nam;
nam = lua_tostring(L, -1);
if (lua_getmetatable(L, -2)) {
lua_pushstring(L, nam);
lua_rawget(L, -2);
} else
lua_pushnil(L);
}
return 1;
}