lua-users home
lua-l archive

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


2013/10/3 Tim Hill <drtimhill@gmail.com>:

> No problem. I think the full implementation looks something like this:
>
> [A] Assume there are two "hidden" state values inside a table (managed, of course, by the Lua table C code)..
> -- t.nLength: The "length" of the sequence
> -- t.bSeq: A boolean that is true when the table contains a sequence, false otherwise.
> (These are both per-table values.)

Where sequence has been redefined to:

> We use the term sequence to denote a table where, _at all times for the life of the table_,
> the set of all positive numeric keys is equal to {1..n} for some integer n, which is called
> the length of the sequence."

Assuming that "a table is a sequence" and "a table contains a sequence" mean the
same thing, the implementation therefore aims to keep track of the sequence-ness
and the length at the cost of two state values.

So `t[0.5]="half"` would break the sequenceness, but `t[0]=0` would not.
It's a quirk of the current definition too, but does not carry over to
spoiling the table library.

> [B] At table creation time (constructor):
> -- Set t.nLen = 0
> -- Set n.bSeq = true
> (Thus all new tables have a length of zero and are sequences.)
>
> [C] New "table.rawlen()" behavior (in Lua pseudo code):
>
> function rawlen(t)
>         if not t.bSeq then return nil else return t.nLen end
> end
>
> (This takes of care of not returning invalid lengths when not a sequence.)
>
> [D] New "table.rawset()" behavior (in Lua pseudo code):
>
> function rawest(t, k, v)
>         if t.bSeq and (type(k) == "number") and (k >= 1) then   -- Is "k" within a sequence?
>                 if not isInteger(k) then                                                        -- Non-integral >= 1, break the sequence
>                         t.bSeq = false
>                 else
>                         if v == nil then
>                                 if k < t.nLen then t.bSeq = false end           -- Creating an interior hole
>                                 if k == t.nLen then t.nLen = k - 1              -- Trimming last item off sequence
>                         else
>                                 if k > t.nLen + 1 then t.bSeq = false end       -- Creating a hole beyond end of sequence
>                                 if k == t.nLen + 1 then t.nLen = k end  -- Extending sequence
>                         end
>                 end
>         end
>         -- (Now do legacy rawest() logic here)
> end

Now the `t[0.5]` break has been hard-coded. Not sure I like that.

> This is actually very low-cost code in C .. notice how non-numeric keys bypass it all, and
> most checks are simple logic tests.

Dirk

PS Note how well-behaved I have been in not giving any references to
23 previous threads
on almost this topic, containing 932 messages, some of which propose
almost this solution.