انتقل إلى المحتوى

وحدة:table/empty

من ويكاموس، القاموس الحر
local table_get_metamethod = "Module:table/getMetamethod"

local next = next
local pairs = pairs
local pairs_default_iter = pairs{}

local function get_metamethod(...)
	get_metamethod = require(table_get_metamethod)
	return get_metamethod(...)
end

-- Not possible to simply iterate with a for-loop, since removing a key means
-- it can't be given to next() on the subsequent iteration. Instead, repeatedly
-- giving next() the initial state and key will either return some valid key,
-- which can then be removed, or nil, once the table is empty.
local function empty_raw(t, iter, state, init)
	while true do
		local k = iter(state, init)
		if k == nil then
			return t
		end
		t[k] = nil
	end
end

--[==[
Given a table, sets all keys to {nil}. If `raw` is set, then metamethods will be ignored.

Warning: this function is only recommended for tables with a small handful of keys, where reusing a table will avoid creating a large number of temporary objects. In the vast majority of situations, it is more efficient to simply create a new table.]==]
return function(t, raw)
	if raw then
		return empty_raw(t, next, t)
	end
	-- If `raw` is not set, try to check for a __pairs metamethod. The check
	-- will fail if there's a protected metatable, but if it succeeds and
	-- there's no __pairs metamethod, use empty_raw() as an optimisation.
	local success, __pairs = get_metamethod(t, "__pairs")
	if success and __pairs == nil then
		return empty_raw(t, next, t)
	end
	-- If the iterator returned by the __pairs metamethod is just the default
	-- pairs iterator or next(), use empty_raw() with the returned state and
	-- key. This is most likely to happen if a protected metatable doesn't have
	-- a __pairs metamethod.
	local iter, state, k = pairs(t)
	if iter == pairs_default_iter or iter == next then
		return empty_raw(t, iter, state, k)
	end
	-- If the iterator returns nothing, `t` is already empty.
	k = iter(state, k)
	if k == nil then
		return t -- already empty
	end
	-- Otherwise, build a table of keys first, then iterate over it to remove
	-- keys from `t`, which ensures removals don't disrupt the loop.
	local keys = {[k] = true}
	for k in iter, state, k do
		keys[k] = true
	end
	for k in next, keys do
		t[k] = nil
	end
	return t
end