Modul:index
Tampilan
Dokumentasi untuk modul ini dapat dibuat di Modul:index/doc
local export = {}
local math_module = "Module:math"
local error = error
local format = string.format
local tostring = tostring
local type = type
local function to_integer(...)
to_integer = require(math_module).to_integer
return to_integer(...)
end
local function input_err(i, funcname, param)
local idx_type = type(i)
error(format(
"bad argument #%d to 'index.%s' (integer expected, got %s)",
param, funcname, idx_type == "number" and tostring(i) or idx_type
), 4)
end
local function get_index(i, obj, func, neg1_nil, funcname, param)
i = to_integer(i) or input_err(i, funcname, param)
-- A relative index of -1 refers to the final index. For many functions,
-- it makes no difference if the final index is nil or -1, so if the
-- `neg1_nil` flag is set and the index is -1, return nil to avoid having
-- to call `func`.
if neg1_nil and i == -1 then
return nil, obj, func
elseif i < 0 then
if func ~= nil then
obj, func = func(obj), nil
end
i = obj + i + 1
end
return i, obj, func
end
function export.absolute(obj, i, func, i_min, i_max)
i, obj, func = get_index(i, obj, func, false, "absolute", 2)
if i_min ~= nil then
i_min, obj, func = get_index(i_min, obj, func, false, "absolute", 4)
if i < i_min then
i = i_min
end
end
if i_max ~= nil then
i_max, obj, func = get_index(i_max, obj, func, false, "absolute", 5)
if i_min and i_min > i_max then
error("bad arguments #4 and #5 to 'index.absolute' (`i_min` cannot be greater than `i_max`)", 2)
elseif i > i_max then
i = i_max
end
end
return i
end
function export.range(obj, i, j, func, always_infer_upper, i_min, j_max)
-- Canonicalize `i`, or otherwise default to 1.
if i == nil then
i = 1
else
i, obj, func = get_index(i, obj, func, false, "range", 2)
end
-- Get the minimum value for `i`. This is 1 by default, because a start
-- index of 0 is always equivalent to 1 for most functions (e.g. string.byte
-- and string.sub). However, many module functions have checks like
-- "while i <= j" or "if i > j" that won't, therefore, handle (0, 0) like
-- (1, 0), so converting 0 to 1 avoids the need to special-case it. If
-- `i_min_allow_0` is set, the minimum defaults to 0 instead (including when
-- the input is nil), which may be needed if 0 represents the position
-- before the first index.
if i_min == nil then
i_min = 1
else
i_min, obj, func = get_index(i_min, obj, func, false, "range", 5)
end
-- Set `i` as the minimum value if it hasn't been specified.
if i < i_min then
i = i_min
end
-- Canonicalize `j`, which will default to the end if not given. By default,
-- this may be implied by returning nil for `j` (even if the input is -1),
-- to avoid calling `func` unnecessarily.
if j ~= nil then
j, obj, func = get_index(j, obj, func, not always_infer_upper, "range", 3)
end
-- Get the maximum value for `j` (if any).
if j_max ~= nil then
j_max, obj, func = get_index(j_max, obj, func, not always_infer_upper, "range", 6)
end
-- If `j` is not set but `j_max` has a value, use that. Otherwise, if
-- `always_infer_upper` is set then give the length of `obj`.
if not j then
j = j_max or always_infer_upper and (not func and obj or func(obj)) or nil
-- Ensure `j` does not exceed `j_max`.
elseif j_max and j > j_max then
j = j_max
end
-- The minimum value for `j` is i - 1, which is equivalent to a range of
-- 0 length (e.g. string.find("", "") returns (1, 0)).
local j_min = i - 1
if j and j < j_min then
j = j_min
end
return i, j
end
return export