lua-users home
lua-l archive

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


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.