Hrm. Maybe putting the table iteration hook in __pairs, rather than __next, is the better choice.
If lua_next() respected an iteration metamethod, then most C table iterations would pick up an extra O(n) overhead cost.
And __pairs also gives you the power to use a state variable other than the table itself, which can be handy.
I'd still like to have a version of next() available in Lua that respects proxy tables -- though that's easy enough to get:
One can use a similar trick at the API level to make a version of lua_next() that respects the __pairs metamethod -- but, there's enough extra overhead in each call that you probably want to be careful about just where you use it.
int lua_nextmeta (lua_State *L, int i) {
int oldtop=lua_gettop(L);
if (!luaL_getmetafield(L,i, "__pairs")) {
return lua_next(L,i);
}
if(i<0) {
i=lua_gettop(L)+i;
}
lua_checkstack(L,2);
lua_pushvalue(L,i); // ...,k,__pairs, t
lua_call(L,1,2); // ...,k,iterfun,s
lua_pushvalue(L,oldtop); // ...,k,iterfun,s,k
lua_remove(L,oldtop); //...,iterfun,s,k
lua_call(L,2,2); // ..., k2, v2
if(lua_isnil(L,-2)) {
lua_pop(L,2);
return 0;
}
return 1;
}