lua-users home
lua-l archive

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


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