local p =
local ustring = mw.ustringlocal libraryUtil = require "libraryUtil"local checkType = libraryUtil.checkTypelocal checkTypeMulti = libraryUtil.checkTypeMulti
local iterableTypes =
local _checkCache = local function _check(funcName, expectType) if type(expectType)
"table" then if not (nilOk and arg
-- Iterate over UTF-8-encoded codepoints in string.local function iterString(str) local iter = string.gmatch(str, "[%z\1-\127\194-\244][\128-\191]*") local i = 0 local function iterator i = i + 1 local char = iter if char then return i, char end end return iteratorend
-- funcName and startArg are for argument type-checking.-- The varargs (...) can be either an iterator and its optional state and start-- value, or an iterable type, in which case the function calls the appropriate-- iterator generator function.local function getIteratorTriplet(funcName, startArg, ...) local t = type(...) if t
"string" then return iterString(first) elseif first[1] ~= nil then return ipairs(first) else return pairs(first) endend
function p.chain(func1, func2, ...) return func1(func2(...))end
-- map(function(number) return number ^ 2 end,-- ) --> -- map(function (char) return string.char(string.byte(char) - 0x20) end,-- "abc") --> -- Two argument formats:-- map(func, iterable)-- map(func, iterator[, state[, start_value]])-- func is a function that takes a maximum of two return values of the iterator-- in reverse order. They are supplied in reverse order because the ipairs-- iterator returns the index before the value, but the value is most often more-- important than the index.
-- Any need for map that retains original keys, rather than creating an array?function p.map(func, keepOriginalKeys, ...) checkType("map", 1, func, "function") local iter, state, start_value if type(keepOriginalKeys)
p.mapIter = p.map
local function fold(func, result, ...) checkType("fold", 1, func, "function") local iter, state, start_value = getIteratorTriplet("fold", 3, ...) for val1, val2 in iter, state, start_value do result = func(result, val2, val1, state) end return resultendp.fold = fold
function p.count(func, ...) checkType("count", 1, func, "function") return fold(function (count, val) if func(val) then return count + 1 end return count end, 0, ...)end
function p.forEach(func, ...) checkType("forEach", 1, func, "function") local iter, state, start_value = getIteratorTriplet("forEach", 2, ...) for val1, val2 in iter, state, start_value do func(val2, val1, state) end return nilend
--------------------------------------------------- From http://lua-users.org/wiki/CurriedLua.-- reverse(...) : take some tuple and return a tuple of elements in reverse order---- e.g. "reverse(1,2,3)" returns 3,2,1local function reverse(...) -- reverse args by building a function to do it, similar to the unpack example local function reverseHelper(acc, v, ...) if select("#", ...)
function p.curry(func, numArgs) -- currying 2-argument functions seems to be the most popular application numArgs = numArgs or 2 -- no sense currying for 1 arg or less if numArgs <= 1 then return func end -- helper takes an argTrace function, and number of arguments remaining to be applied local function curryHelper(argTrace, n) if n
-------------------------------------------------
-- some(function(val) return val % 2
-- all(function(val) return val % 2
function p.indexOf(func, ...) local iter, state, start_value = getIteratorTriplet("indexOf", 2, ...) if type(func)
val2 then return val1 end end else error("value to search for is nil") end return nilend
function p.filter(func, ...) local check = _check checkType("filter", 1, func, "function") local new_t = local new_i = 0 local iter, state, start_value = getIteratorTriplet("filter", 2, ...) for val1, val2 in iter, state, start_value do if func(val2, val1, state) then new_i = new_i + 1 new_t[new_i] = val1 end end return new_tend
function p.range(low, high) low = low - 1 return function if low < high then low = low + 1 return low end endend
--------------------------------- Fancy stufflocal function capture(...) local vals = return function return unpack(vals) endend
-- Log input and output of function.-- Receives a function and returns a modified form of that function.function p.logReturnValues(func, prefix) return function(...) local inputValues = capture(...) local returnValues = capture(func(...)) if prefix then mw.log(prefix, inputValues) mw.log(returnValues) else mw.log(inputValues) mw.log(returnValues) end return returnValues endend
p.log = p.logReturnValues
-- Convenience function to make all functions in a table log their input and output.function p.logAll(t) for k, v in pairs(t) do if type(v)
----- M E M O I Z A T I O N------- metamethod that does the work-- Currently supports one argument and one return value.local func_key = local function callMethod(self, x) local output = self[x] if not output then output = self[func_key](x) self[x] = output end return outputend
-- shared metatablelocal mt =
-- Create callable table.function p.memoize(func) return setmetatable(mt)end
-------------------------------
return p