lua-users home
lua-l archive

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


So... in lack of this magical site for working on common code, I
submit for consideration a suitable array implementation:

local list_mt = { }

local table_pack = table.pack or function ( ... ) return { n = select
( "#" , ... ) , ... } end

function list ( ... )
	return setmetatable ( table_pack ( ... ) , list_mt )
end

local function check_list ( l )
	return assert ( getmetatable ( l ) == list_mt , "Not a list" )
end

local function insert ( l , i , v )
	check_list ( l )
	local sz = #l
	local new_sz = sz + 1
	assert ( type ( i ) == "number" and i > 0 and i <= new_sz , "Invalid index" )
	
	for k = sz , i , -1 do
		rawset ( l , k + 1 , rawget ( l , k ) )
	end
	rawset ( l , i , v )
	l.n = new_sz
	return l
end

local function append ( l , ... )
	check_list ( l )
	local args = table_pack ( ... )
	local sz = #l
	for i = 1 , args.n do
		rawset ( l , sz + i , rawget ( args , i ) )
	end
	l.n = sz + args.n
	return l
end

local function remove ( l , i )
	check_list ( l )
	local sz = #l
	assert ( type ( i ) == "number" and i > 0 and i <= sz )
	local v = rawget ( l , i )
	for k = i , sz do
		rawset ( l , k , rawget ( l , k + 1 ) )
	end
	l.n = sz - 1
	return l
end

local function concat  ( l1 , l2 )
	check_list ( l1 )
	check_list ( l2 )
	local r = list ( l1:unpack ( 1 , #l1 ) )
	r:append ( l2:unpack ( 1 , #l2 ) )
	return r
end

local function length ( l )
	check_list ( l )
	return rawget ( l , "n" )
end

list_mt.__index = {
	insert = insert ;
	append = append ;
	remove = remove ;
	length = length ;
	unpack = unpack ;
	tostring = table.concat ;
	sort = table.sort ;
}
list_mt.__len = length ;
list_mt.__ipairs = function ( l )
	local sz = #l
	return function ( l , last_i )
		local i = last_i + 1
		if i > sz then return nil end
		return i , rawget ( l , i )
	end
end ;
list_mt.__pairs = list_mt.__ipairs
list_mt.__newindex = function ( l , i , v )
	assert ( type ( i ) == "number" and i > 0 and i < #l + 1 )
	rawset ( l , i , v )
end ;
list_mt.__add = append
list_mt.__sub = remove
list_mt.__concat = concat