• Subject: Re: pairs(t, skey) and ipairs(t, skey)
• From: Tim Hill <drtimhill@...>
• Date: Wed, 2 Oct 2013 22:08:17 -0700

```On Oct 2, 2013, at 6:45 PM, Sean Conner <sean@conman.org> wrote:

> It was thus said that the Great Tim Hill once stated:
>>
>> First, it's a bit odd to have to work-around the # operator like this
>> (witness the number of times this comes up in this forum). Second, I'm not
>> sure why you take such issue with my suggested language change .. what is
>> actually wrong with it?
>>
>> Present behavior:
>> With a sequence: # returns valid length
>> Without a sequence: # returns arbitrary integer value that is easy to mistake for a length
>>
>> Suggested behavior:
>> With a sequence: # returns valid length
>> Without a sequence: # returns nil
>>
>> Why is the suggested behavior bad?
>
>  I misunderstood the suggestion to also include support for nils in a
> sequence.  I apologize for any confusion on my part.
>
>  -spc
>

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.)

[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

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

--Tim

```