Modül:grc-araçlar/şablonlar/functional
Bu belgeleme Modül:grc-araçlar/şablonlar/functional/belge (düzenle | geçmiş) sayfasından yansıtılmaktadır. Arayüz düzenleyicilerinin deney yapabilmeleri için ayrıca Modül:grc-araçlar/şablonlar/functional/deneme tahtası sayfası kullanılabilir.
local export = {}
local ustring = mw.ustring
local libraryUtil = require "libraryUtil"
local checkType = libraryUtil.checkType
local checkTypeMulti = libraryUtil.checkTypeMulti
local iterableTypes = { "table", "string" }
local function _check(funcName, expectType)
if type(expectType) == "string" then
return function(argIndex, arg, nilOk)
return checkType(funcName, argIndex, arg, expectType, nilOk)
end
else
return function(argIndex, arg, expectType, nilOk)
if type(expectType) == "table" then
return checkTypeMulti(funcName, argIndex, arg, expectType, nilOk)
else
return checkType(funcName, argIndex, arg, expectType, nilOk)
end
end
end
end
-- Calling len once means fewer operations, but assumes string will not be
-- modified during iteration.
local function iterString(str)
local length = ustring.len(str)
local sub = ustring.sub
local function iterator(str, i)
i = i + 1
if i <= length then
return i, sub(str, i, i)
else
return nil
end
end
return iterator, str, 0
end
function export.chain(func1, func2, ...)
return func1(func2(...))
end
-- map(function(number) return number ^ 2 end,
-- { 1, 2, 3 }) --> { 1, 4, 9 }
-- map(function (char) return string.byte(char) end,
-- "abc") --> { 97, 98, 99 }
function export.map(func, iterable)
local check = _check 'map'
check(1, func, "function")
check(2, iterable, iterableTypes)
local array = {}
local iterator = type(iterable) == "string" and iterString or ipairs
for i, val in iterator(iterable) do
array[i] = func(val, i, iterable)
end
return array
end
function export.forEach(func, iterable)
local check = _check 'forEach'
check(1, func, "function")
check(2, iterable, iterableTypes)
local iterator = type(iterable) == "string" and iterString or ipairs
for i, val in iterator(iterable) do
func(val, i, iterable)
end
return nil
end
-------------------------------------------------
-- 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,1
local function reverse(...)
-- reverse args by building a function to do it, similar to the unpack() example
local function reverseHelper(acc, v, ...)
if select('#', ...) == 0 then
return v, acc()
else
return reverseHelper(function () return v, acc() end, ...)
end
end
-- initial acc is the end of the list
return reverseHelper(function () return end, ...)
end
function export.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 == 0 then
-- kick off argTrace, reverse argument list, and call the original function
return func(reverse(argTrace()))
else
-- "push" argument (by building a wrapper function) and decrement n
return function (onearg)
return curryHelper(function () return onearg, argTrace() end, n - 1)
end
end
end
-- push the terminal case of argTrace into the function first
return curryHelper(function () return end, numArgs)
end
-------------------------------------------------
local function capture(...)
local vals = {...}
return function()
return unpack(vals)
end
end
-- Find out what functions are returning by making a new version that still
-- returns the same values, but also logs them.
function export.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()
end
end
-- Make all functions in a table (for instance, a module's export table) log
-- their return values, but otherwise function normally.
function export.logAll(t)
for k, v in pairs(t) do
if type(v) == "function" then
t[k] = export.logReturnValues(v, tostring(k))
end
end
return t
end
-----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 function callMethod(self, x)
local output = self[x]
if not output then
output = self.func(x)
self[x] = output
end
return output
end
-- shared metatable
local mt = { __call = callMethod }
-- Create callable table.
function export.memoize(func)
return setmetatable({ func = func }, mt)
end
-------------------------------
-- some(function(val) return val % 2 == 0 end,
-- { 2, 3, 5, 7, 11 }) --> true
function export.some(func, t)
if t[i] then -- array
for i, v in ipairs(t) do
if func(v, i, t) then
return true
end
end
else
for k, v in pairs(t) do
if func(v, k, t) then
return true
end
end
end
return false
end
-- all(function(val) return val % 2 == 0 end,
-- { 2, 4, 8, 10, 12 }) --> true
function export.all(func, t)
if t[i] then -- array
for i, v in ipairs(t) do
if not func(v, i, t) then
return false
end
end
else
for k, v in pairs(t) do
if not func(v, k, t) then
return false
end
end
end
return true
end
local function toHex(number)
return ("0x%X"):format(number)
end
local function printCodepoint(char)
return toHex(ustring.codepoint(char))
end
function export.test(frame)
local str = "ΒΓΔΖΘΚΛΜΝΞΠΡΣΣΤΦΧΨβγδζθκλμνξπρσςτφχψ"
local midpoint = ustring.len(str) / 2
local new_string = export.map(function(character, i)
return character .. ustring.sub(str, i + midpoint, i + midpoint)
end,
ustring.sub(str, 1, midpoint))
return table.concat(new_string)
end
return export