Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to produce ipairs (as opposed to pairs) behavior in the C API

Tags:

c

api

lua

In Lua, pairs and ipairs can iterate over the same elements in a different order:

> t = {[1]=1, [2]=2, [3]=3}
> for k,v in pairs(t) do print(k,v) end
2       2
1       1
3       3
> for k,v in ipairs(t) do print(k,v) end
1       1
2       2
3       3

When using the C API, I see only one tool for iterating over a table: the lua_next() function which acts very much like the pairs() Lua function which produces the 2-1-3 order shown above.

I am looking for an efficient C method for iterating over the integer keys of a table sequentially(a C API version of ipairs).

Naively, I considered:

int tableLength = luaL_len(L, tableIndex);
for (i=0, i++, i>tableLength){   
    // if t[i] is not null ...
}

but I am unclear of potential performance issues where table sizes do not match the number of consecutive integer keys:

t = {[1]=1, [2]=2, [4]=4}     -- has a (reported) length of 4
t = {[1]=1, [2]=2, [40000]=4} -- has a (reported) length of 2

If this is indeed the way ipairs does it, then is there an easy way to start using lua_next with the last found integer key to continue to walk the rest of the table avoiding walking the integer-key portion again? Is there a chance I will see some integer keys twice by doing so?

like image 437
Paul Avatar asked Jan 03 '13 23:01

Paul


1 Answers

t = {[1]=1, [2]=2, [4]=4}     -- has a length of 4

Well there's your problem right there; that does not have a length of 4. You might think it does, and #t might return 4. But as far as the Lua API is concerned, the length of this table is undefined.

Lua 5.1 states:

The length of a table t is defined to be any integer index n such that t[n] is not nil and t[n+1] is nil; moreover, if t1 is nil, n can be zero. For a regular array, with non-nil values from 1 to a given n, its length is exactly that n, the index of its last value. If the array has "holes" (that is, nil values between other non-nil values), then #t can be any of the indices that directly precedes a nil value (that is, it may consider any such nil value as the end of the array).

Lua 5.2 is rather more explicit:

the length of a table t is only defined if the table is a sequence, that is, the set of its positive numeric keys is equal to {1..n} for some integer n. In that case, n is its length. Note that a table like

 {10, 20, nil, 40}

is not a sequence, because it has the key 4 but does not have the key 3. (So, there is no n such that the set {1..n} is equal to the set of positive numeric keys of that table.) Note, however, that non-numeric keys do not interfere with whether a table is a sequence.

But in both cases, the length is undefined.

like image 181
Nicol Bolas Avatar answered Nov 25 '22 08:11

Nicol Bolas