Module:Array: Difference between revisions

From The Deadlock Wiki
Jump to navigation Jump to search
osrsw>Talulah
m remove log calls
osrsw>Habblet
m import changes from rsw:Module:Enum
Line 1: Line 1:
-- <nowiki> awawa
-- <nowiki> awawa
local libraryUtil = require('libraryUtil')
local libraryUtil = require('libraryUtil')
local checkType = libraryUtil.checkType
local checkTypeMulti = libraryUtil.checkTypeMulti
local p = {}
local p = {}


function p.any(enum, fn, clone)
function p.all(enum, fn, clone)
libraryUtil.checkType('Module:Enum.any', 1, enum, 'table')
checkType('Module:Enum.all', 1, enum, 'table')
libraryUtil.checkType('Module:Enum.any', 2, fn, 'function', true)
checkType('Module:Enum.all', 2, fn, 'function', true)
libraryUtil.checkType('Module:Enum.any', 3, clone, 'boolean', true)
checkType('Module:Enum.all', 3, clone, 'boolean', true)
if clone then enum = mw.clone(enum) end
if clone then enum = mw.clone(enum) end
fn = fn or function(item) return item end
fn = fn or function(item) return item end
for _, item in ipairs(enum) do
for _, item in ipairs(enum) do
if fn(item) then
if not fn(item) then
return true
return false
end
end
end
end
return false
return true
end
end


function p.all(enum, fn, clone)
function p.any(enum, fn, clone)
libraryUtil.checkType('Module:Enum.all', 1, enum, 'table')
checkType('Module:Enum.any', 1, enum, 'table')
libraryUtil.checkType('Module:Enum.all', 2, fn, 'function', true)
checkType('Module:Enum.any', 2, fn, 'function', true)
libraryUtil.checkType('Module:Enum.all', 3, clone, 'boolean', true)
checkType('Module:Enum.any', 3, clone, 'boolean', true)
if clone then enum = mw.clone(enum) end
if clone then enum = mw.clone(enum) end
fn = fn or function(item) return item end
fn = fn or function(item) return item end
for _, item in ipairs(enum) do
for _, item in ipairs(enum) do
if not fn(item) then
if fn(item) then
return false
return true
end
end
end
end
return true
return false
end
 
function p.contains(enum, elem, clone)
checkType('Module:Enum.contains', 1, enum, 'table')
checkType('Module:Enum.contains', 3, clone, 'boolean', true)
if clone then enum = mw.clone(enum); elem = mw.clone(elem) end
return p.any(enum, function(item) return item == elem end)
end
end


function p.each(enum, fn, clone)
function p.each(enum, fn, clone)
libraryUtil.checkType('Module:Enum.each', 1, enum, 'table')
checkType('Module:Enum.each', 1, enum, 'table')
libraryUtil.checkType('Module:Enum.each', 2, fn, 'function')
checkType('Module:Enum.each', 2, fn, 'function')
libraryUtil.checkType('Module:Enum.each', 3, clone, 'boolean', true)
checkType('Module:Enum.each', 3, clone, 'boolean', true)
if clone then enum = mw.clone(enum) end
if clone then enum = mw.clone(enum) end
for _, item in ipairs(enum) do
for _, item in ipairs(enum) do
Line 42: Line 51:


function p.filter(enum, fn, clone)
function p.filter(enum, fn, clone)
libraryUtil.checkType('Module:Enum.filter', 1, enum, 'table')
checkType('Module:Enum.filter', 1, enum, 'table')
libraryUtil.checkType('Module:Enum.filter', 2, fn, 'function', true)
checkType('Module:Enum.filter', 2, fn, 'function', true)
libraryUtil.checkType('Module:Enum.filter', 3, clone, 'boolean', true)
checkType('Module:Enum.filter', 3, clone, 'boolean', true)
if clone then enum = mw.clone(enum) end
if clone then enum = mw.clone(enum) end
fn = fn or function(item) return item end
fn = fn or function(item) return item end
Line 57: Line 66:


function p.find(enum, fn, default, clone)
function p.find(enum, fn, default, clone)
libraryUtil.checkType('Module:Enum.find', 1, enum, 'table')
checkType('Module:Enum.find', 1, enum, 'table')
libraryUtil.checkType('Module:Enum.find', 2, fn, 'function')
checkType('Module:Enum.find', 2, fn, 'function')
libraryUtil.checkType('Module:Enum.find', 4, clone, 'boolean', true)
checkType('Module:Enum.find', 4, clone, 'boolean', true)
if clone then enum = mw.clone(enum); default = mw.clone(default) end
if clone then enum = mw.clone(enum); default = mw.clone(default) end
for _, item in ipairs(enum) do
for _, item in ipairs(enum) do
Line 70: Line 79:


function p.find_index(enum, fn, default, clone)
function p.find_index(enum, fn, default, clone)
libraryUtil.checkType('Module:Enum.find_index', 1, enum, 'table')
checkType('Module:Enum.find_index', 1, enum, 'table')
libraryUtil.checkType('Module:Enum.find_index', 2, fn, 'function')
checkType('Module:Enum.find_index', 2, fn, 'function')
libraryUtil.checkType('Module:Enum.find_index', 4, clone, 'boolean', true)
checkType('Module:Enum.find_index', 4, clone, 'boolean', true)
if clone then enum = mw.clone(enum); default = mw.clone(default) end
if clone then enum = mw.clone(enum); default = mw.clone(default) end
for index, item in ipairs(enum) do
for index, item in ipairs(enum) do
Line 80: Line 89:
end
end
return default
return default
end
function p.newIncrementor(start, step)
checkType('Module:Enum.newIncrementor', 1, start, 'number', true)
checkType('Module:Enum.newIncrementor', 2, step, 'number', true)
step = step or 1
local n = (start or 1) - step
local obj = {}
return setmetatable(obj, {
__call = function() n = n + step return n end,
__tostring = function() return n end,
__index = function() return n end,
__newindex = function(self, k, v)
if k == 'step' and type(v) == 'number' then
step = v
elseif type(v) == 'number' then
n = v
end
end,
__concat = function(x, y) return tostring(x) .. tostring(y) end
})
end
function p.intersect(enum1, enum2, clone)
checkType('Module:Enum.intersect', 1, enum1, 'table')
checkType('Module:Enum.intersect', 2, enum2, 'table')
checkType('Module:Enum.intersect', 3, clone, 'boolean', true)
if clone then enum1 = mw.clone(enum1); enum2 = mw.clone(enum2) end
local enum2Elements = {}
local res = {}
p.each(enum2, function(item) enum2Elements[item] = true end)
p.each(enum1, function(item)
if enum2Elements[item] then
table.insert(res, item)
end
end)
return res
end
function p.intersects(enum1, enum2, clone)
checkType('Module:Enum.intersects', 1, enum1, 'table')
checkType('Module:Enum.intersects', 2, enum2, 'table')
checkType('Module:Enum.intersects', 3, clone, 'boolean', true)
if clone then enum1 = mw.clone(enum1); enum2 = mw.clone(enum2) end
return p.any(enum1, function(item1) return p.any(enum2, function(item2) return item1==item2 end) end)
end
function p.insert(enum1, enum2, index, clone)
checkType('Module:Enum.insert', 1, enum1, 'table')
checkType('Module:Enum.insert', 2, enum2, 'table')
checkType('Module:Enum.insert', 3, index, 'number', true)
checkType('Module:Enum.insert', 4, clone, 'boolean', true)
if clone then enum1 = mw.clone(enum1); enum2 = mw.clone(enum2) end
local len1 = #enum1
local len2 = #enum2
index = index or (len1 + 1)
local res = {}
for i = 1, (len1 + len2) do
if i < index then
res[i] = enum1[i]
elseif i < (index + len2) then
res[i] = enum2[i - index + 1]
else
res[i] = enum1[i - len2]
end
end
return res
end
end


function p.map(enum, fn, clone)
function p.map(enum, fn, clone)
libraryUtil.checkType('Module:Enum.map', 1, enum, 'table')
checkType('Module:Enum.map', 1, enum, 'table')
libraryUtil.checkType('Module:Enum.map', 2, fn, 'function')
checkType('Module:Enum.map', 2, fn, 'function')
libraryUtil.checkType('Module:Enum.map', 3, clone, 'boolean', true)
checkType('Module:Enum.map', 3, clone, 'boolean', true)
if clone then enum = mw.clone(enum) end
if clone then enum = mw.clone(enum) end
local r = {}
local r = {}
Line 96: Line 174:


function p.max_by(enum, fn, clone)
function p.max_by(enum, fn, clone)
libraryUtil.checkType('Module:Enum.max_by', 1, enum, 'table')
checkType('Module:Enum.max_by', 1, enum, 'table')
libraryUtil.checkType('Module:Enum.max_by', 2, fn, 'function')
checkType('Module:Enum.max_by', 2, fn, 'function')
libraryUtil.checkType('Module:Enum.max_by', 3, clone, 'boolean', true)
checkType('Module:Enum.max_by', 3, clone, 'boolean', true)
if clone then enum = mw.clone(enum) end
if clone then enum = mw.clone(enum) end
return unpack(p.reduce(enum, function(new, old)
return unpack(p.reduce(enum, function(new, old)
Line 104: Line 182:
return y > old[2] and {new, y} or old
return y > old[2] and {new, y} or old
end, {0, 0}))
end, {0, 0}))
end
function p.range(start, stop, step)
checkType('Module:Enum.range', 1, start, 'number')
checkType('Module:Enum.range', 2, stop, 'number', true)
checkType('Module:Enum.range', 3, step, 'number', true)
local array = {}
if not stop then
stop = start
start = 1
end
local j = 1
for i = start, stop, step or 1 do
array[j] = i
j = j + 1
end
return array
end
end


function p.reduce(enum, fn, accumulator, clone)
function p.reduce(enum, fn, accumulator, clone)
libraryUtil.checkType('Module:Enum.reduce', 1, enum, 'table')
checkType('Module:Enum.reduce', 1, enum, 'table')
libraryUtil.checkType('Module:Enum.reduce', 2, fn, 'function')
checkType('Module:Enum.reduce', 2, fn, 'function')
libraryUtil.checkType('Module:Enum.reduce', 4, clone, 'boolean', true)
checkType('Module:Enum.reduce', 4, clone, 'boolean', true)
if clone then enum = mw.clone(enum); accumulator = mw.clone(accumulator) end
if clone then enum = mw.clone(enum); accumulator = mw.clone(accumulator) end
local acc = accumulator
local acc = accumulator
Line 123: Line 218:


function p.reject(enum, fn, clone)
function p.reject(enum, fn, clone)
libraryUtil.checkType('Module:Enum.reject', 1, enum, 'table')
checkType('Module:Enum.reject', 1, enum, 'table')
libraryUtil.checkType('Module:Enum.reject', 2, fn, 'function')
checkTypeMulti('Module:Enum.reject', 2, fn, {'function', 'table', 'nil'})
libraryUtil.checkType('Module:Enum.reject', 3, clone, 'boolean', true)
checkType('Module:Enum.reject', 3, clone, 'boolean', true)
if clone then enum = mw.clone(enum) end
if clone then enum = mw.clone(enum) end
fn = fn or function(item) return item end
fn = fn or function(item) return item end
local r = {}
local r = {}
for index, item in ipairs(enum) do
if type(fn) == 'function' then
if not fn(item, index) then
for index, item in ipairs(enum) do
table.insert(r, item)
if not fn(item, index) then
table.insert(r, item)
end
end
else
local rejectMap = {}
for _, item in ipairs(fn) do
rejectMap[item] = true
end
for _, item in ipairs(enum) do
if not rejectMap[item] then
table.insert(r, item)
end
end
end
end
end
return r
return r
end
function p.range(start, stop, step)
libraryUtil.checkType('Module:Enum.range', 1, start, 'number')
libraryUtil.checkType('Module:Enum.range', 2, stop, 'number', true)
libraryUtil.checkType('Module:Enum.range', 3, step, 'number', true)
local array = {}
if not stop then
stop = start
start = 1
end
for i = start, stop, step or 1 do
table.insert(array, i)
end
return array
end
end


function p.scan(enum, fn, accumulator, clone)
function p.scan(enum, fn, accumulator, clone)
libraryUtil.checkType('Module:Enum.scan', 1, enum, 'table')
checkType('Module:Enum.scan', 1, enum, 'table')
libraryUtil.checkType('Module:Enum.scan', 2, fn, 'function')
checkType('Module:Enum.scan', 2, fn, 'function')
libraryUtil.checkType('Module:Enum.scan', 4, clone, 'boolean', true)
checkType('Module:Enum.scan', 4, clone, 'boolean', true)
if clone then enum = mw.clone(enum); accumulator = mw.clone(accumulator) end
if clone then enum = mw.clone(enum); accumulator = mw.clone(accumulator) end
local acc = accumulator
local acc = accumulator
Line 171: Line 263:


function p.slice(enum, start, finish, clone)
function p.slice(enum, start, finish, clone)
libraryUtil.checkType('Module:Enum.slice', 1, enum, 'table')
checkType('Module:Enum.slice', 1, enum, 'table')
libraryUtil.checkType('Module:Enum.slice', 2, start, 'number', true)
checkType('Module:Enum.slice', 2, start, 'number', true)
libraryUtil.checkType('Module:Enum.slice', 3, finish, 'number', true)
checkType('Module:Enum.slice', 3, finish, 'number', true)
libraryUtil.checkType('Module:Enum.slice', 4, clone, 'boolean', true)
checkType('Module:Enum.slice', 4, clone, 'boolean', true)
if clone then enum = mw.clone(enum) end
if clone then enum = mw.clone(enum) end
start = start or 1
start = start or 1
Line 188: Line 280:


function p.split(enum, count, clone)
function p.split(enum, count, clone)
libraryUtil.checkType('Module:Enum.split', 1, enum, 'table')
checkType('Module:Enum.split', 1, enum, 'table')
libraryUtil.checkType('Module:Enum.split', 2, count, 'number')
checkType('Module:Enum.split', 2, count, 'number')
libraryUtil.checkType('Module:Enum.split', 3, clone, 'boolean', true)
checkType('Module:Enum.split', 3, clone, 'boolean', true)
if clone then enum = mw.clone(enum) end
if clone then enum = mw.clone(enum) end
if #enum < count then
if #enum < count then
Line 211: Line 303:


function p.sum(enum, clone)
function p.sum(enum, clone)
libraryUtil.checkType('Module:Enum.sum', 1, enum, 'table')
checkType('Module:Enum.sum', 1, enum, 'table')
libraryUtil.checkType('Module:Enum.sum', 2, clone, 'boolean', true)
checkType('Module:Enum.sum', 2, clone, 'boolean', true)
if clone then enum = mw.clone(enum) end
if clone then enum = mw.clone(enum) end
return p.reduce(enum, function(x, y) return x + y end)
return p.reduce(enum, function(x, y) return x + y end)
Line 218: Line 310:


function p.take(enum, count, clone)
function p.take(enum, count, clone)
libraryUtil.checkType('Module:Enum.take', 1, enum, 'table')
checkType('Module:Enum.take', 1, enum, 'table')
libraryUtil.checkType('Module:Enum.take', 2, count, 'number')
checkType('Module:Enum.take', 2, count, 'number')
libraryUtil.checkType('Module:Enum.take', 3, clone, 'boolean', true)
checkType('Module:Enum.take', 3, clone, 'boolean', true)
if clone then enum = mw.clone(enum) end
if clone then enum = mw.clone(enum) end
local x, _ = p.split(enum, count)
local x, _ = p.split(enum, count)
Line 227: Line 319:


function p.take_every(enum, n, clone)
function p.take_every(enum, n, clone)
libraryUtil.checkType('Module:Enum.take_every', 1, enum, 'table')
checkType('Module:Enum.take_every', 1, enum, 'table')
libraryUtil.checkType('Module:Enum.take_every', 2, n, 'number')
checkType('Module:Enum.take_every', 2, n, 'number')
libraryUtil.checkType('Module:Enum.take_every', 3, clone, 'boolean', true)
checkType('Module:Enum.take_every', 3, clone, 'boolean', true)
if clone then enum = mw.clone(enum) end
if clone then enum = mw.clone(enum) end
local r = {}
local r = {}
Line 238: Line 330:
end
end
return r
return r
end
function p.take_from(enum, index, count)
checkType('Module:Enum.take_from', 1, enum, 'table')
checkType('Module:Enum.take_from', 2, index, 'number')
checkType('Module:Enum.take_from', 3, count, 'number')
local x, _ = p.split(p.reject(enum,
function(item, idx)
return idx < index
end
), count)
return x
end
end


function p.unique(enum, fn, clone)
function p.unique(enum, fn, clone)
libraryUtil.checkType('Module:Enum.unique', 1, enum, 'table')
checkType('Module:Enum.unique', 1, enum, 'table')
libraryUtil.checkType('Module:Enum.unique', 2, fn, 'function', true)
checkType('Module:Enum.unique', 2, fn, 'function', true)
libraryUtil.checkType('Module:Enum.unique', 3, clone, 'boolean', true)
checkType('Module:Enum.unique', 3, clone, 'boolean', true)
if clone then enum = mw.clone(enum) end
if clone then enum = mw.clone(enum) end
fn = fn or function(item) return item end
fn = fn or function(item) return item end
Line 259: Line 363:


function p.zip(enums, clone)
function p.zip(enums, clone)
libraryUtil.checkType('Module:Enum.zip', 1, enums, 'table')
checkType('Module:Enum.zip', 1, enums, 'table')
libraryUtil.checkType('Module:Enum.zip', 2, clone, 'boolean', true)
checkType('Module:Enum.zip', 2, clone, 'boolean', true)
if clone then enums = mw.clone(enums) end
if clone then enums = mw.clone(enums) end
local r = {}
local r = {}
Line 272: Line 376:
end
end
return r
return r
end
function p.take_from(enum, index, count)
libraryUtil.checkType('Module:Enum.take_from', 1, enum, 'table')
libraryUtil.checkType('Module:Enum.take_from', 2, index, 'number')
libraryUtil.checkType('Module:Enum.take_from', 3, count, 'number')
local x, _ = p.split(p.reject(enum,
function(item, idx)
return idx < index
end
), count)
return x
end
function p.intersect(enum1, enum2, clone)
libraryUtil.checkType('Module:Enum.intersect', 1, enum1, 'table')
libraryUtil.checkType('Module:Enum.intersect', 2, enum2, 'table')
libraryUtil.checkType('Module:Enum.intersect', 3, clone, 'boolean', true)
if clone then enum1 = mw.clone(enum1); enum2 = mw.clone(enum2) end
return p.any(enum1, function(item1) return p.any(enum2, function(item2) return item1==item2 end) end)
end
function p.contains(enum, elem, clone)
libraryUtil.checkType('Module:Enum.contains', 1, enum, 'table')
libraryUtil.checkType('Module:Enum.contains', 3, clone, 'boolean', true)
if clone then enum = mw.clone(enum); elem = mw.clone(elem) end
return p.any(enum, function(item) return item == elem end)
end
end


return p
return p
-- </nowiki>
-- </nowiki>

Revision as of 16:30, 31 August 2020

Documentation for this module may be created at Module:Array/doc

-- <nowiki> awawa
local libraryUtil = require('libraryUtil')
local checkType = libraryUtil.checkType
local checkTypeMulti = libraryUtil.checkTypeMulti
local p = {}

function p.all(enum, fn, clone)
	checkType('Module:Enum.all', 1, enum, 'table')
	checkType('Module:Enum.all', 2, fn, 'function', true)
	checkType('Module:Enum.all', 3, clone, 'boolean', true)
	if clone then enum = mw.clone(enum) end
	fn = fn or function(item) return item end
	for _, item in ipairs(enum) do
		if not fn(item) then
			return false
		end
	end
	return true
end

function p.any(enum, fn, clone)
	checkType('Module:Enum.any', 1, enum, 'table')
	checkType('Module:Enum.any', 2, fn, 'function', true)
	checkType('Module:Enum.any', 3, clone, 'boolean', true)
	if clone then enum = mw.clone(enum) end
	fn = fn or function(item) return item end
	for _, item in ipairs(enum) do
		if fn(item) then
			return true
		end
	end
	return false
end

function p.contains(enum, elem, clone)
	checkType('Module:Enum.contains', 1, enum, 'table')
	checkType('Module:Enum.contains', 3, clone, 'boolean', true)
	if clone then enum = mw.clone(enum); elem = mw.clone(elem) end
	return p.any(enum, function(item) return item == elem end)
end

function p.each(enum, fn, clone)
	checkType('Module:Enum.each', 1, enum, 'table')
	checkType('Module:Enum.each', 2, fn, 'function')
	checkType('Module:Enum.each', 3, clone, 'boolean', true)
	if clone then enum = mw.clone(enum) end
	for _, item in ipairs(enum) do
		fn(item)
	end
end

function p.filter(enum, fn, clone)
	checkType('Module:Enum.filter', 1, enum, 'table')
	checkType('Module:Enum.filter', 2, fn, 'function', true)
	checkType('Module:Enum.filter', 3, clone, 'boolean', true)
	if clone then enum = mw.clone(enum) end
	fn = fn or function(item) return item end
	local r = {}
	for _, item in ipairs(enum) do
		if fn(item) then
			table.insert(r, item)
		end
	end
	return r
end

function p.find(enum, fn, default, clone)
	checkType('Module:Enum.find', 1, enum, 'table')
	checkType('Module:Enum.find', 2, fn, 'function')
	checkType('Module:Enum.find', 4, clone, 'boolean', true)
	if clone then enum = mw.clone(enum); default = mw.clone(default) end
	for _, item in ipairs(enum) do
		if fn(item) then
			return item
		end
	end
	return default
end

function p.find_index(enum, fn, default, clone)
	checkType('Module:Enum.find_index', 1, enum, 'table')
	checkType('Module:Enum.find_index', 2, fn, 'function')
	checkType('Module:Enum.find_index', 4, clone, 'boolean', true)
	if clone then enum = mw.clone(enum); default = mw.clone(default) end
	for index, item in ipairs(enum) do
		if fn(item) then
			return index
		end
	end
	return default
end

function p.newIncrementor(start, step)
	checkType('Module:Enum.newIncrementor', 1, start, 'number', true)
	checkType('Module:Enum.newIncrementor', 2, step, 'number', true)
	step = step or 1
	local n = (start or 1) - step
	local obj = {}
	return setmetatable(obj, {
		__call = function() n = n + step return n end,
		__tostring = function() return n end,
		__index = function() return n end,
		__newindex = function(self, k, v)
			if k == 'step' and type(v) == 'number' then
				step = v
			elseif type(v) == 'number' then
				n = v
			end
		end,
		__concat = function(x, y) return tostring(x) .. tostring(y) end
	})
end

function p.intersect(enum1, enum2, clone)
	checkType('Module:Enum.intersect', 1, enum1, 'table')
	checkType('Module:Enum.intersect', 2, enum2, 'table')
	checkType('Module:Enum.intersect', 3, clone, 'boolean', true)
	if clone then enum1 = mw.clone(enum1); enum2 = mw.clone(enum2) end
	local enum2Elements = {}
	local res = {}
	p.each(enum2, function(item) enum2Elements[item] = true end)
	p.each(enum1, function(item)
		if enum2Elements[item] then
			table.insert(res, item)
		end
	end)
	return res
end

function p.intersects(enum1, enum2, clone)
	checkType('Module:Enum.intersects', 1, enum1, 'table')
	checkType('Module:Enum.intersects', 2, enum2, 'table')
	checkType('Module:Enum.intersects', 3, clone, 'boolean', true)
	if clone then enum1 = mw.clone(enum1); enum2 = mw.clone(enum2) end
	return p.any(enum1, function(item1) return p.any(enum2, function(item2) return item1==item2 end) end)
end

function p.insert(enum1, enum2, index, clone)
	checkType('Module:Enum.insert', 1, enum1, 'table')
	checkType('Module:Enum.insert', 2, enum2, 'table')
	checkType('Module:Enum.insert', 3, index, 'number', true)
	checkType('Module:Enum.insert', 4, clone, 'boolean', true)
	if clone then enum1 = mw.clone(enum1); enum2 = mw.clone(enum2) end
	local len1 = #enum1
	local len2 = #enum2
	index = index or (len1 + 1)
	local res = {}

	for i = 1, (len1 + len2) do
		if i < index then
			res[i] = enum1[i]
		elseif i < (index + len2) then
			res[i] = enum2[i - index + 1]
		else
			res[i] = enum1[i - len2]
		end
	end

	return res
end

function p.map(enum, fn, clone)
	checkType('Module:Enum.map', 1, enum, 'table')
	checkType('Module:Enum.map', 2, fn, 'function')
	checkType('Module:Enum.map', 3, clone, 'boolean', true)
	if clone then enum = mw.clone(enum) end
	local r = {}
	for _, item in ipairs(enum) do
		local temp = fn(item) -- Only use first returned item
		table.insert(r, temp)
	end
	return r
end

function p.max_by(enum, fn, clone)
	checkType('Module:Enum.max_by', 1, enum, 'table')
	checkType('Module:Enum.max_by', 2, fn, 'function')
	checkType('Module:Enum.max_by', 3, clone, 'boolean', true)
	if clone then enum = mw.clone(enum) end
	return unpack(p.reduce(enum, function(new, old)
		local y = fn(new)
		return y > old[2] and {new, y} or old
	end, {0, 0}))
end

function p.range(start, stop, step)
	checkType('Module:Enum.range', 1, start, 'number')
	checkType('Module:Enum.range', 2, stop, 'number', true)
	checkType('Module:Enum.range', 3, step, 'number', true)
	local array = {}
	if not stop then
		stop = start
		start = 1
	end
	local j = 1
	for i = start, stop, step or 1 do
		array[j] = i
		j = j + 1
	end
	return array
end

function p.reduce(enum, fn, accumulator, clone)
	checkType('Module:Enum.reduce', 1, enum, 'table')
	checkType('Module:Enum.reduce', 2, fn, 'function')
	checkType('Module:Enum.reduce', 4, clone, 'boolean', true)
	if clone then enum = mw.clone(enum); accumulator = mw.clone(accumulator) end
	local acc = accumulator
	for index, item in ipairs(enum) do
		if index == 1 and not accumulator then
			acc = item
		else
			acc = fn(item, acc)
		end
	end
	return acc
end

function p.reject(enum, fn, clone)
	checkType('Module:Enum.reject', 1, enum, 'table')
	checkTypeMulti('Module:Enum.reject', 2, fn, {'function', 'table', 'nil'})
	checkType('Module:Enum.reject', 3, clone, 'boolean', true)
	if clone then enum = mw.clone(enum) end
	fn = fn or function(item) return item end
	local r = {}
	if type(fn) == 'function' then
		for index, item in ipairs(enum) do
			if not fn(item, index) then
				table.insert(r, item)
			end
		end
	else
		local rejectMap = {}
		for _, item in ipairs(fn) do
			rejectMap[item] = true
		end
		for _, item in ipairs(enum) do
			if not rejectMap[item] then
				table.insert(r, item)
			end
		end
	end
	return r
end

function p.scan(enum, fn, accumulator, clone)
	checkType('Module:Enum.scan', 1, enum, 'table')
	checkType('Module:Enum.scan', 2, fn, 'function')
	checkType('Module:Enum.scan', 4, clone, 'boolean', true)
	if clone then enum = mw.clone(enum); accumulator = mw.clone(accumulator) end
	local acc = accumulator
	local r = {}
	for index, item in ipairs(enum) do
		if index == 1 and not accumulator then
			acc = item
		else
			acc = fn(item, acc)
		end
		table.insert(r, acc)
	end
	return r
end

function p.slice(enum, start, finish, clone)
	checkType('Module:Enum.slice', 1, enum, 'table')
	checkType('Module:Enum.slice', 2, start, 'number', true)
	checkType('Module:Enum.slice', 3, finish, 'number', true)
	checkType('Module:Enum.slice', 4, clone, 'boolean', true)
	if clone then enum = mw.clone(enum) end
	start = start or 1
	finish = finish or #enum
	local r = {}
	for index, item in ipairs(enum) do
		if index >= start and index <= finish then
			table.insert(r, item)
		end
	end
	return r
end

function p.split(enum, count, clone)
	checkType('Module:Enum.split', 1, enum, 'table')
	checkType('Module:Enum.split', 2, count, 'number')
	checkType('Module:Enum.split', 3, clone, 'boolean', true)
	if clone then enum = mw.clone(enum) end
	if #enum < count then
		return enum, {}
	elseif count < 1 then
		return {}, enum
	end

	local x = {}
	local y = {}

	for i = 1, #enum do
		table.insert(
			i <= count and x or y,
			enum[i]
		)
	end
	return x, y
end

function p.sum(enum, clone)
	checkType('Module:Enum.sum', 1, enum, 'table')
	checkType('Module:Enum.sum', 2, clone, 'boolean', true)
	if clone then enum = mw.clone(enum) end
	return p.reduce(enum, function(x, y) return x + y end)
end

function p.take(enum, count, clone)
	checkType('Module:Enum.take', 1, enum, 'table')
	checkType('Module:Enum.take', 2, count, 'number')
	checkType('Module:Enum.take', 3, clone, 'boolean', true)
	if clone then enum = mw.clone(enum) end
	local x, _ = p.split(enum, count)
	return x
end

function p.take_every(enum, n, clone)
	checkType('Module:Enum.take_every', 1, enum, 'table')
	checkType('Module:Enum.take_every', 2, n, 'number')
	checkType('Module:Enum.take_every', 3, clone, 'boolean', true)
	if clone then enum = mw.clone(enum) end
	local r = {}
	for index, item in ipairs(enum) do
		if (index - 1) % n == 0 then
			table.insert(r, item)
		end
	end
	return r
end

function p.take_from(enum, index, count)
	checkType('Module:Enum.take_from', 1, enum, 'table')
	checkType('Module:Enum.take_from', 2, index, 'number')
	checkType('Module:Enum.take_from', 3, count, 'number')
	local x, _ = p.split(p.reject(enum,
		function(item, idx)
			return idx < index
		end
	), count)
	return x
end

function p.unique(enum, fn, clone)
	checkType('Module:Enum.unique', 1, enum, 'table')
	checkType('Module:Enum.unique', 2, fn, 'function', true)
	checkType('Module:Enum.unique', 3, clone, 'boolean', true)
	if clone then enum = mw.clone(enum) end
	fn = fn or function(item) return item end
	local r = {}
	local hash = {}
	for _, item in ipairs(enum) do
		local id = fn(item)
		if not hash[id] then
			table.insert(r, item)
			hash[id] = true
		end
	end
	return r
end

function p.zip(enums, clone)
	checkType('Module:Enum.zip', 1, enums, 'table')
	checkType('Module:Enum.zip', 2, clone, 'boolean', true)
	if clone then enums = mw.clone(enums) end
	local r = {}
	local _, longest = p.max_by(enums, function(enum) return #enum end)
	for i = 1, longest do
		local q = {}
		for j = 1, #enums do
			table.insert(q, enums[j][i])
		end
		table.insert(r, q)
	end
	return r
end

return p
-- </nowiki>