[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: idiomatic table iteration
- From: Daurnimator <quae@...>
- Date: Thu, 25 Aug 2016 11:07:51 +1000
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?).