[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: pairs(t, skey) and ipairs(t, skey)
- From: Paul K <paulclinger@...>
- Date: Wed, 2 Oct 2013 09:55:40 -0700
On Wed, Oct 2, 2013 at 3:51 AM, Luiz Henrique de Figueiredo
<lhf@tecgraf.puc-rio.br> wrote:
>> Why would you need that? If you care that a table is a sequence, then either
>> you have created the table and know it or you have been handed a table
> There are tedious-but-sure methods of finding the 'hash' part
> (non-array) but they are not quick and rarely needed except when
> pretty-printing arbitrary tables.
Steve pointed to the precise case I have: serialization and
pretty-printing of large tables with numerical keys. Currently I first
iterate over 1..#t indexes (mostly for performance and formatting
reasons) and it would be nice to be able to do two things: (1) check
if there is anything else (elements in the array part that didn't get
into #t or the hash part), (2) start iteration from the hash part.
I understand that #2 is likely to require API or algorithm changes,
but #1 seems to be totally doable, just not available from Lua API. It
should be possible to compare #t with t->sizearray to check if there
is anything else and also check isdummy(t->node) to find if there is
any hash part.
As to #2, this was another incorrect assumption I had that after
reading the source code of luaH_next I assumed that the array part is
always iterated over first, and only then the hash part is used:
int i = findindex(L, t, key); /* find original element */
for (i++; i < t->sizearray; i++) { /* try first array part */
...
for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */
But given Dirk's earlier example (t={a='a', b='b', c='c', [3]=3,
[2]=2,[1]=1}), there are clearly cases when #t > 0 (which seems to
indicate that there is some array part) and yet pairs() returns keys
in some random order (mixing those from array and hash parts). What am
I missing?
Actually, I may be slowly getting to the answer. By reading luaH_getn,
it seems like #t will check if any indexes that may match numeric
indexes (unbound_search), which means that #t *may* return non-zero
results on tables that don't have *any* array part. This is probably
something that happens in Dirk's example: the array part is empty, but
there is a hash part that "looks" like array part and this is being
reported by #t. So, maybe my assumption about luaH_next was correct
after all and it does go over the array part first; it's just in that
case there was no array part (and I assumed that there was because #t
was >0).
I think the "sequence" in #t operator description is misleading (or at
least needs to be supported with some examples and gotchas): (1) #t
can be less than t->sizearray if there are holes in the array part,
but it's not guaranteed to stop at the first hole as it does binary
search simply looking for n ~= nil and n+1 == nil, and (2) #t can be
more than t->sizearray when t->sizearray == 0 and there are happen to
be numeric keys in the hash part that form a sequence starting from 1.
Paul.
- References:
- Re: pairs(t, skey) and ipairs(t, skey), Dirk Laurie
- Re: pairs(t, skey) and ipairs(t, skey), Paul K
- Re: pairs(t, skey) and ipairs(t, skey), Luiz Henrique de Figueiredo
- Re: pairs(t, skey) and ipairs(t, skey), Tim Hill
- Re: pairs(t, skey) and ipairs(t, skey), Luiz Henrique de Figueiredo
- Re: pairs(t, skey) and ipairs(t, skey), steve donovan