มอดูล:User:Erutuon/lang stuff/map

จาก วิกิพจนานุกรม พจนานุกรมเสรี
local Map_methods = {}
-- metatable for Maps
local Map = { __index = Map_methods }

-- Cache Module:array here.
local array_constructor

-- Names of functions in [[Module:table]].
local table_methods = {
	"shallowcopy", "deepcopy", "keysToList", "size", "sortedPairs"
}
local create_array = { "keysToList" }
local create_map = { "shallowcopy" }
local aliases = { keys = "keysToList" }

-- Behaves like "next", but filters out methods from "Map_methods".
function Map_methods:next(v)
	for k, v in next, self, v do
		if not Map_methods[k] then
			return k, v
		end
	end
end

function Map_methods:pairs()
	return Map_methods.next, self, nil
end

function Map_methods:map(func)
	local new_t = {}
	for k, v in self:pairs() do
		new_t[k] = func(v, k, self)
	end
	return Map:new(new_t)
end

function Map_methods:filter(func)
	local new_t = {}
	for k, v in self:pairs() do
		if func(v, k, self) then
			new_t[k] = v
		end
	end
	return Map:new(new_t)
end

function Map_methods:values(key)
	array_constructor = array_constructor or require "Module:array"
	local arr = array_constructor()
	for k, v in self:pairs() do
		arr:insert(v)
	end
	return arr
end

-- Create array of values sorted by key and concatenate it with a separator.
function Map_methods:sortedConcat(sep, comp)
	array_constructor = array_constructor or require "Module:array"
	local arr = array_constructor()
	for k, v in self:sortedPairs(comp) do
		arr:insert(v)
	end
	return arr:concat(sep)
end

function Map_methods:log()
	mw.logObject(self)
	return self
end

local function wrap_in_array_constructor(func)
	array_constructor = array_constructor or require "Module:array"
	return function (...)
		return array_constructor(func(...))
	end
end

local function wrap_in_map_constructor(func)
	return function (...)
		return Map:new(func(...))
	end
end

local m_table

-- Grab additional functions from [[Module:table]].
local Map_methods_mt = {}
setmetatable(Map_methods, Map_methods_mt)
function Map_methods_mt:__index(key)
	if type(key) ~= "string" then
		return nil
	end
	
	-- Convert underscores to camel case: num_keys -> numKeys.
	key = key:gsub("_(.)", string.upper)
	
	key = aliases[key] or key
	
	local val = rawget(Map_methods, key)
	if val then
		return val
	end
	
	m_table = m_table or require "Module:table"
	
	if key == "toArray" then
		val = require "Module:array".from
	elseif m_table.contains(table_methods, key) then
		val = m_table[key]
		
		if m_table.contains(create_array, key) then
			val = wrap_in_array_constructor(val)
		elseif m_table.contains(create_map, key) then
			val = wrap_in_map_constructor(val)
		end
	end
	
	if val then
		Map_methods[key] = val
		return val
	end
end

function Map:new(...)
	local map
	if type((...)) == "table" then
		map = ...
		
		local mt = getmetatable(map)
		if mt and mt.mw_loadData then
			m_table = m_table or require "Module:table"
			map = m_table.shallowcopy(map)
		end
	else
		map = {}
	end
	
	return setmetatable(map, self)
end

return Map