-- Prosody IM
-- Copyright (C) 2008-2009 Matthew Wild
-- Copyright (C) 2008-2009 Waqas Hussain
--
-- This project is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information.
--
local t_insert , t_sort , t_remove , t_concat
= table.insert , table.sort , table.remove , table.concat ;
local array = { } ;
local array_base = { } ;
local array_methods = { } ;
local array_mt = { __index = array_methods , __tostring = function ( array ) return array : concat ( " , " ) ; end } ;
local function new_array ( _ , t )
return setmetatable ( t or { } , array_mt ) ;
end
function array_mt . __add ( a1 , a2 )
local res = new_array ( ) ;
return res : append ( a1 ) : append ( a2 ) ;
end
setmetatable ( array , { __call = new_array } ) ;
function array_base . map ( outa , ina , func )
for k , v in ipairs ( ina ) do
outa [ k ] = func ( v ) ;
end
return outa ;
end
function array_base . filter ( outa , ina , func )
local inplace , start_length = ina == outa , # ina ;
local write = 1 ;
for read = 1 , start_length do
local v = ina [ read ] ;
if func ( v ) then
outa [ write ] = v ;
write = write + 1 ;
end
end
if inplace and write < start_length then
for i = write , start_length do
outa [ i ] = nil ;
end
end
return outa ;
end
function array_base . sort ( outa , ina , ... )
if ina ~= outa then
outa : append ( ina ) ;
end
t_sort ( outa , ... ) ;
return outa ;
end
--- These methods only mutate
function array_methods : random ( )
return self [ math.random ( 1 , # self ) ] ;
end
function array_methods : shuffle ( outa , ina )
local len = # self ;
for i = 1 , # self do
local r = math.random ( i , len ) ;
self [ i ] , self [ r ] = self [ r ] , self [ i ] ;
end
return self ;
end
function array_methods : reverse ( )
local len = # self - 1 ;
for i = len , 1 , - 1 do
self : push ( self [ i ] ) ;
self : pop ( i ) ;
end
return self ;
end
function array_methods : append ( array )
local len , len2 = # self , # array ;
for i = 1 , len2 do
self [ len + i ] = array [ i ] ;
end
return self ;
end
array_methods.push = table.insert ;
array_methods.pop = table.remove ;
array_methods.concat = table.concat ;
array_methods.length = function ( t ) return # t ; end
--- These methods always create a new array
function array . collect ( f , s , var )
local t , var = { } ;
while true do
var = f ( s , var ) ;
if var == nil then break ; end
table.insert ( t , var ) ;
end
return setmetatable ( t , array_mt ) ;
end
---
-- Setup methods from array_base
for method , f in pairs ( array_base ) do
local method = method ; -- Yes, this is necessary :)
local base_method = f ;
-- Setup global array method which makes new array
array [ method ] = function ( old_a , ... )
local a = new_array ( ) ;
return base_method ( a , old_a , ... ) ;
end
-- Setup per-array (mutating) method
array_methods [ method ] = function ( self , ... )
return base_method ( self , self , ... ) ;
end
end
_G.array = array ;
module ( " array " ) ;
return array ;