Jump to content

Module:relation

ពីWiktionary

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

local export = {}

local math_module = "Module:math"
local string_compare_module = "Module:string/compare"

local rawequal = rawequal
local require = require
local select = select
local type = type

local function is_NaN(...)
	is_NaN = require(math_module).is_NaN
	return is_NaN(...)
end

local function sign(...)
	sign = require(math_module).sign
	return sign(...)
end

local function string_compare(...)
	string_compare =  require(string_compare_module)
	return string_compare(...)
end

--[==[
The equality operator {==} as a function.]==]
function export.equal(a, b)
	return a == b
end
export.eq = export.equal

--[==[
The inequality operator {~=} as a function.]==]
function export.not_equal(a, b)
	return a ~= b
end
export.ne = export.not_equal

--[==[
Returns {true} if two variables refer to the same object; roughly equivalent to the {{code|py|is}} keyword in Python.

This differs from {==} or {rawequal()}, in that it accounts for strange objects like [[w:NaN|NaN]], which always return false for equality checks. As such, it should only be used when it is absolutely necessary to distinguish objects by identity rather than value (e.g. during memoization), and is not a drop-in replacement for {==} or {rawequal()}.]==]
function export.is(a, b)
	-- rawequal() will correctly filter almost everything.
	if rawequal(a, b) then
		-- If equal, return true unless one is +0 and the other -0, as these
		-- behave differently under certain conditions: e.g. 1/(+0) is infinity,
		-- but 1/(-0) is -infinity.
		return a ~= 0 or 1 / a == 1 / b
	end
	-- If not equal, return false unless a and b are both NaN and have the same
	-- sign. NaN will return false when compared with itself, so compare with
	-- ~= (since there's no need for rawequal(), as Lua never invokes an __eq
	-- metamethod when comparing an object with itself).
	return is_NaN(a) and is_NaN(b) and sign(a) == sign(b)
end

--[==[
The less-than operator {<} as a function, incorporating the fixes for string comparison implemented in [[Module:string/compare]].

Note: this function should not be used with {table.sort()}; instead, use [[Module:compare]], which contains various special sorting considerations. If only dealing with a single data type, it will be more performant to call one of its auxiliary functions directly: [[Module:string/compare]] (for strings), [[Module:math/compare]] (for numbers) or [[Module:table/compare]] (for tables).]==]
function export.less_than(a, b)
	-- Generate the default value, which will throw any type errors.
	local default = a < b
	if type(a) == "string" then
		return string_compare(a, b)
	end
	return default
end
export.lt = export.less_than

--[==[
The less-than-or-equal operator {<=} as a function, incorporating the fixes for string comparison implemented in [[Module:string/compare]].]==]
function export.less_than_or_equal(a, b)
	if a == b then
		return true
	end
	local default = a <= b
	if type(a) == "string" then
		return string_compare(a, b)
	end
	return default
end
export.le = export.less_than_or_equal

--[==[
The greater-than operator {>} as a function, incorporating the fixes for string comparison implemented in [[Module:string/compare]].]==]
function export.greater_than(a, b)
	local default = a > b
	if type(a) == "string" then
		return string_compare(b, a)
	end
	return default
end
export.gt = export.greater_than

--[==[
The greater-than-or-equal operator {>=} as a function, incorporating the fixes for string comparison implemented in [[Module:string/compare]].]==]
function export.greater_than_or_equal(a, b)
	if a == b then
		return true
	end
	local default = a >= b
	if type(a) == "string" then
		return string_compare(b, a)
	end
	return default
end
export.ge = export.greater_than_or_equal

--[==[
Logical XOR (exclusive OR): true only if exactly one input argument is true. Considers {false} and {nil} as logically false (falsy), and anything else as logically true (truthy).

Note: for consistency with the in-built {and} and {or} operators, the precise return value depends on the input arguments:
* If one argument is logically true and the other logically false, returns the truthy argument.
* If both are logically true, returns {false}.
* If both are logically false, returns the (falsy) second argument.]==]
function export.xor(a, b)
	if not a then
		return b
	elseif not b then
		return a
	end
	return false
end

--[==[
Given an arbitrary number of input arguments, returns the first value which is not {nil}. Roughly equivalent to a chain of `??` operators in various languages.]==]
function export.null_coalesce(v, ...)
	if v ~= nil then
		return v
	end
	v = ...
	if v ~= nil then
		return v
	end
	for i = 2, select("#", ...) do
		local v = select(i, ...)
		if v ~= nil then
			return v
		end
	end
end

return export