Jump to content

Модул:require when needed

Аз Wiktionary

Функсияи ёрирасон, ки метавонад ба ҷои require истифода шавад, агар мутмаин набошад, ки модули мавриди назар лозим аст. Агар модул аллакай бор карда шуда бошад, пас он танҳо баргардонида мешавад; агар он надошта бошад, пас он то он даме, ки бори аввал истифода шавад, бор карда намешавад.

Ин одатан ҳангоми муайян кардани тағирёбандаҳо дар оғози модул муфид аст.

Шаблон:module cat


local getmetatable = getmetatable
local ipairs = ipairs
local loaded = package.loaded
local pairs = pairs
local require = require
local select = select
local setmetatable = setmetatable
local tostring = tostring
local unpack = unpack

local function get_nested(obj, ...)
	local n = select("#", ...)
	if n == 0 then
		return obj
	end
	obj = obj[...]
	for i = 2, n do
		obj = obj[select(i, ...)]
	end
	return obj
end

local function get_obj(mt)
	local obj = require(mt[1])
	if #mt > 1 then
		obj = get_nested(obj, unpack(mt, 2))
	end
	mt[0] = obj
	return obj
end

local function __call(self, ...)
	local mt = getmetatable(self)
	local obj = mt[0]
	if obj == nil then
		obj = get_obj(mt)
	end
	return obj(...)
end

local function __index(self, k)
	local mt = getmetatable(self)
	local obj = mt[0]
	if obj == nil then
		obj = get_obj(mt)
	end
	return obj[k]
end

local function __ipairs(self)
	local mt = getmetatable(self)
	local obj = mt[0]
	if obj == nil then
		obj = get_obj(mt)
	end
	return ipairs(obj)
end

local function __newindex(self, k, v)
	local mt = getmetatable(self)
	local obj = mt[0]
	if obj == nil then
		obj = get_obj(mt)
	end
	obj[k] = v
end

local function __pairs(self)
	local mt = getmetatable(self)
	local obj = mt[0]
	if obj == nil then
		obj = get_obj(mt)
	end
	return pairs(obj)
end

local function __tostring(self)
	local mt = getmetatable(self)
	local obj = mt[0]
	if obj == nil then
		obj = get_obj(mt)
	end
	return tostring(obj)
end

return function(modname, ...)
	local mod = loaded[modname]
	if mod ~= nil then
		return get_nested(mod, ...)
	end
	return setmetatable({}, {
		modname,
		__call = __call,
		__index = __index,
		__ipairs = __ipairs,
		__newindex = __newindex,
		__pairs = __pairs,
		__tostring = __tostring,
		-- TODO: other metamethods, if needed.
		...
	})
end