lua-users home
lua-l archive

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


On 25 August 2016 at 10:56, Patrick Donnelly <batrick@batbytes.com> wrote:
> So as far as I've seen, most C code uses the Lua manual's example code
> structure to iterate tables. Namely:
>
> lua_pushnil(L);
> while (lua_next(L, idx) != 0) {
>   /* code here */
>   lua_pop(L, 1); /* pop value */
> }
>
> This structure goes back to the Lua 4.0 manual [1].
>
> I noticed that the C for loop results in a more natural construction:
>
> for (lua_pushnil(L); lua_next(L, idx); lua_pop(L, 1)) {
>    /* code here always has the key/value pair on the stack */
> }
>
> One of the advantages I see is that the for loop code block must
> follow good stack discipline (not leaving anything on the stack or
> incidentally removing the value) because the lua_pop must always pop
> the value. For example, this code is not very flexible to future
> changes:
>
> lua_pushnil(L);
> while (lua_next(L, idx)) {
>   lua_pushboolean(L, 1);
>   lua_rawset(L, someidx); /* value removed by rawset */
> }
>
> So does anyone use the for loop construct? I appreciate the manual
> version is more clear in how it works but it is taken as the idiomatic
> way to iterate tables. (In fact, the Lua source code uses that style
> in the base libraries.)
>
> [1] https://www.lua.org/manual/4.0/manual.html#5.12
>
> --
> Patrick Donnelly
>

Neither of those styles take into account __pairs. If we want to
spread new idioms, I suggest we pick one that will respect __pairs.

That said, lua_pop is really just lua_gettop + lua_settop. To reduce
the need for stack discipline we can just use settop instead, perhaps
something like:

for (int base_idx = (lua_pushnil(L), lua_gettop(L)); lua_next(L, idx);
lua_settop(L, baseidx))

I'm not sure if this is correct (will C evaluate the pushnil/gettop in
a defined order?).