Browse Source

Import lua-functional for plugins stuff.

tags/0.9.0
Vsevolod Stakhov 9 years ago
parent
commit
195bfd320c
3 changed files with 998 additions and 0 deletions
  1. 3
    0
      CMakeLists.txt
  2. 27
    0
      contrib/lua-fun/COPYING.md
  3. 968
    0
      contrib/lua-fun/fun.lua

+ 3
- 0
CMakeLists.txt View File

@@ -1011,6 +1011,9 @@ FOREACH(LUA_PLUGIN ${LUA_PLUGINS})
INSTALL(FILES "src/plugins/lua/${LUA_PLUGIN}" DESTINATION ${PLUGINSDIR}/lua/${_rp})
ENDFOREACH(LUA_PLUGIN)

# Install lua fun library
INSTALL(FILES "contrib/lua-fun/fun.lua" DESTINATION ${PLUGINSDIR}/fun.lua)

# Lua config
INSTALL(CODE "FILE(MAKE_DIRECTORY \$ENV{DESTDIR}${CONFDIR}/lua)")
FILE(GLOB_RECURSE LUA_CONFIGS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/conf/lua"

+ 27
- 0
contrib/lua-fun/COPYING.md View File

@@ -0,0 +1,27 @@
Copying
=======

**Lua Fun** source codes, logo and documentation are distributed under the
**[MIT/X11 License]** - same as Lua and LuaJIT.

Copyright (c) 2013 Roman Tsisyk <roman@tsisyk.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

[MIT/X11 License]: http://www.opensource.org/licenses/mit-license.php

+ 968
- 0
contrib/lua-fun/fun.lua View File

@@ -0,0 +1,968 @@
---
--- Lua Fun - a high-performance functional programming library for LuaJIT
---
--- Copyright (c) 2013 Roman Tsisyk <roman@tsisyk.com>
---
--- Distributed under the MIT/X11 License. See COPYING.md for more details.
---

--------------------------------------------------------------------------------
-- Tools
--------------------------------------------------------------------------------

local return_if_not_empty = function(state_x, ...)
if state_x == nil then
return nil
end
return ...
end

local call_if_not_empty = function(fun, state_x, ...)
if state_x == nil then
return nil
end
return state_x, fun(...)
end

local function deepcopy(orig) -- used by cycle()
local orig_type = type(orig)
local copy
if orig_type == 'table' then
copy = {}
for orig_key, orig_value in next, orig, nil do
copy[deepcopy(orig_key)] = deepcopy(orig_value)
end
else
copy = orig
end
return copy
end

--------------------------------------------------------------------------------
-- Basic Functions
--------------------------------------------------------------------------------

local nil_gen = function(_param, _state)
return nil
end

local string_gen = function(param, state)
local state = state + 1
if state > #param then
return nil
end
local r = string.sub(param, state, state)
return state, r
end

local pairs_gen = pairs({ a = 0 }) -- get the generating function from pairs
local map_gen = function(tab, key)
local value
local key, value = pairs_gen(tab, key)
return key, key, value
end

local iter = function(obj, param, state)
assert(obj ~= nil, "invalid iterator")
if (type(obj) == "function") then
return obj, param, state
elseif (type(obj) == "table" or type(obj) == "userdata") then
if #obj > 0 then
return ipairs(obj)
else
return map_gen, obj, nil
end
elseif (type(obj) == "string") then
if #obj == 0 then
return nil_gen, nil, nil
end
return string_gen, obj, 0
end
error(string.format('object %s of type "%s" is not iterable',
obj, type(obj)))
end

local iter_tab = function(obj)
if type(obj) == "function" then
return obj, nil, nil
elseif type(obj) == "table" and type(obj[1]) == "function" then
return obj[1], obj[2], obj[3]
else
return iter(obj)
end
end

local each = function(fun, gen, param, state)
local gen_x, param_x, state_x = iter(gen, param, state)
repeat
state_x = call_if_not_empty(fun, gen_x(param_x, state_x))
until state_x == nil
end

--------------------------------------------------------------------------------
-- Generators
--------------------------------------------------------------------------------

local range_gen = function(param, state)
local stop, step = param[1], param[2]
local state = state + step
if state >= stop then
return nil
end
return state, state
end

local range_rev_gen = function(param, state)
local stop, step = param[1], param[2]
local state = state + step
if state <= stop then
return nil
end
return state, state
end

local range = function(start, stop, step)
if step == nil then
step = 1
if stop == nil then
stop = start
start = 0
end
end

assert(type(start) == "number", "start must be a number")
assert(type(stop) == "number", "stop must be a number")
assert(type(step) == "number", "step must be a number")
assert(step ~= 0, "step must not be zero")

if (step > 0) then
return range_gen, {stop, step}, start - step
elseif (step < 0) then
return range_rev_gen, {stop, step}, start - step
end
end

local duplicate_table_gen = function(param_x, state_x)
return state_x + 1, unpack(param_x)
end

local duplicate_fun_gen = function(param_x, state_x)
return state_x + 1, param_x(state_x)
end

local duplicate_gen = function(param_x, state_x)
return state_x + 1, param_x
end

local duplicate = function(...)
if select('#', ...) <= 1 then
return duplicate_gen, select(1, ...), 0
else
return duplicate_table_gen, {...}, 0
end
end

local tabulate = function(fun)
assert(type(fun) == "function")
return duplicate_fun_gen, fun, 0
end

local zeros = function()
return duplicate_gen, 0, 0
end

local ones = function()
return duplicate_gen, 1, 0
end

local rands_gen = function(param_x, _state_x)
return 0, math.random(param_x[1], param_x[2])
end

local rands_nil_gen = function(_param_x, _state_x)
return 0, math.random()
end

local rands = function(n, m)
if n == nil and m == nil then
return rands_nil_gen, 0, 0
end
assert(type(n) == "number", "invalid first arg to rands")
if m == nil then
m = n
n = 0
else
assert(type(m) == "number", "invalid second arg to rands")
end
assert(n < m, "empty interval")
return rands_gen, {n, m - 1}, 0
end

--------------------------------------------------------------------------------
-- Slicing
--------------------------------------------------------------------------------

local nth = function(n, gen, param, state)
assert(n > 0, "invalid first argument to nth")
local gen_x, param_x, state_x = iter(gen, param, state)
-- An optimization for arrays and strings
if gen_x == ipairs then
return param_x[n]
elseif gen_x == string_gen then
if n < #param_x then
return string.sub(param_x, n, n)
else
return nil
end
end
for i=1,n-1,1 do
state_x = gen_x(param_x, state_x)
if state_x == nil then
return nil
end
end
return return_if_not_empty(gen_x(param_x, state_x))
end

local head_call = function(state, ...)
if state == nil then
error("head: iterator is empty")
end
return ...
end

local head = function(gen, param, state)
local gen_x, param_x, state_x = iter(gen, param, state)
return head_call(gen_x(param_x, state_x))
end

local tail = function(gen, param, state)
local gen_x, param_x, state_x = iter(gen, param, state)
state_x = gen_x(param_x, state_x)
if state_x == nil then
return nil_gen, nil, nil
end
return gen_x, param_x, state_x
end

local take_n_gen_x = function(i, state_x, ...)
if state_x == nil then
return nil
end
return {i, state_x}, ...
end

local take_n_gen = function(param, state)
local n, gen_x, param_x = param[1], param[2], param[3]
local i, state_x = state[1], state[2]
if i >= n then
return nil
end
return take_n_gen_x(i + 1, gen_x(param_x, state_x))
end

local take_n = function(n, gen, param, state)
assert(n >= 0, "invalid first argument to take_n")
local gen_x, param_x, state_x = iter(gen, param, state)
return take_n_gen, {n, gen, param}, {0, state}
end

local take_while_gen_x = function(fun, state_x, ...)
if state_x == nil or not fun(...) then
return nil
end
return state_x, ...
end

local take_while_gen = function(param, state_x)
local fun, gen_x, param_x = param[1], param[2], param[3]
return take_while_gen_x(fun, gen_x(param_x, state_x))
end

local take_while = function(fun, gen, param, state)
assert(type(fun) == "function", "invalid first argument to take_while")
local gen_x, param_x, state_x = iter(gen, param, state)
return take_while_gen, {fun, gen, param}, state
end

local take = function(n_or_fun, gen, param, state)
if type(n_or_fun) == "number" then
return take_n(n_or_fun, gen, param, state)
else
return take_while(n_or_fun, gen, param, state)
end
end

local drop_n = function(n, gen, param, state)
assert(n >= 0, "invalid first argument to drop_n")
local gen_x, param_x, state_x = iter(gen, param, state)
for i=1,n,1 do
state_x = gen_x(param_x, state_x)
if state_x == nil then
return nil_gen, nil, nil
end
end
return gen_x, param_x, state_x
end

local drop_while_x = function(fun, state_x, ...)
if state_x == nil or not fun(...) then
return state_x, false
end
return state_x, true, ...
end

local drop_while = function(fun, gen, param, state)
assert(type(fun) == "function", "invalid first argument to drop_while")
local gen_x, param_x, state_x = iter(gen, param, state)
local cont, state_x_prev
repeat
state_x_prev = deepcopy(state_x)
state_x, cont = drop_while_x(fun, gen_x(param_x, state_x))
until not cont
if state_x == nil then
return nil_gen, nil, nil
end
return gen_x, param_x, state_x_prev
end

local drop = function(n_or_fun, gen, param, state)
if type(n_or_fun) == "number" then
return drop_n(n_or_fun, gen, param, state)
else
return drop_while(n_or_fun, gen, param, state)
end
end

local split = function(n_or_fun, gen, param, state)
return {take(n_or_fun, gen, param, state)},
{drop(n_or_fun, gen, param, state)}
end

--------------------------------------------------------------------------------
-- Indexing
--------------------------------------------------------------------------------

local index = function(x, gen, param, state)
local i = 1
for _k, r in iter(gen, param, state) do
if r == x then
return i
end
i = i + 1
end
return nil
end

local indexes_gen = function(param, state)
local x, gen_x, param_x = param[1], param[2], param[3]
local i, state_x = state[1], state[2]
local r
while true do
state_x, r = gen_x(param_x, state_x)
if state_x == nil then
return nil
end
i = i + 1
if r == x then
return {i, state_x}, i
end
end
end

local indexes = function(x, gen, param, state)
local gen_x, param_x, state_x = iter(gen, param, state)
return indexes_gen, {x, gen_x, param_x}, {0, state_x}
end

-- TODO: undocumented
local find = function(fun, gen, param, state)
local gen_x, param_x, state_x = filter(fun, gen, param, state)
return return_if_not_empty(gen_x(param_x, state_x))
end

--------------------------------------------------------------------------------
-- Filtering
--------------------------------------------------------------------------------

local filter1_gen = function(fun, gen_x, param_x, state_x, a)
while true do
if state_x == nil or fun(a) then break; end
state_x, a = gen_x(param_x, state_x)
end
return state_x, a
end

-- call each other
local filterm_gen
local filterm_gen_shrink = function(fun, gen_x, param_x, state_x)
return filterm_gen(fun, gen_x, param_x, gen_x(param_x, state_x))
end

filterm_gen = function(fun, gen_x, param_x, state_x, ...)
if state_x == nil then
return nil
end
if fun(...) then
return state_x, ...
end
return filterm_gen_shrink(fun, gen_x, param_x, state_x)
end

local filter_detect = function(fun, gen_x, param_x, state_x, ...)
if select('#', ...) < 2 then
return filter1_gen(fun, gen_x, param_x, state_x, ...)
else
return filterm_gen(fun, gen_x, param_x, state_x, ...)
end
end

local filter_gen = function(param, state_x)
local fun, gen_x, param_x = param[1], param[2], param[3]
return filter_detect(fun, gen_x, param_x, gen_x(param_x, state_x))
end

local filter = function(fun, gen, param, state)
local gen_x, param_x, state_x = iter(gen, param, state)
return filter_gen, {fun, gen_x, param_x}, state_x
end

local grep = function(fun_or_regexp, gen, param, state)
local fun = fun_or_regexp
if type(fun_or_regexp) == "string" then
fun = function(x) return string.find(x, fun_or_regexp) ~= nil end
end
return filter(fun, gen, param, state)
end

local partition = function(fun, gen, param, state)
local neg_fun = function(...)
return not fun(...)
end
local gen_x, param_x, state_x = iter(gen, param, state)
return {filter(fun, gen_x, param_x, state_x)},
{filter(neg_fun, gen_x, param_x, state_x)}
end

--------------------------------------------------------------------------------
-- Reducing
--------------------------------------------------------------------------------

local foldl_call = function(fun, start, state, ...)
if state == nil then
return nil, start
end
return state, fun(start, ...)
end

local foldl = function(fun, start, gen, param, state)
local gen_x, param_x, state_x = iter(gen, param, state)
while true do
state_x, start = foldl_call(fun, start, gen_x(param_x, state_x))
if state_x == nil then
break;
end
end
return start
end

local length = function(gen, param, state)
local gen, param, state = iter(gen, param, state)
if gen == ipairs or gen == string_gen then
return #param
end
local len = 0
repeat
state = gen(param, state)
len = len + 1
until state == nil
return len - 1
end

local is_null = function(gen, param, state)
local gen_x, param_x, state_x = iter(gen, param, state)
return gen_x(param_x, deepcopy(state_x)) == nil
end

local is_prefix_of = function(iter_x, iter_y)
local gen_x, param_x, state_x = iter_tab(iter_x)
local gen_y, param_y, state_y = iter_tab(iter_y)

local r_x, r_y
for i=1,10,1 do
state_x, r_x = gen_x(param_x, state_x)
state_y, r_y = gen_y(param_y, state_y)
if state_x == nil then
return true
end
if state_y == nil or r_x ~= r_y then
return false
end
end
end

local all = function(fun, gen, param, state)
local gen_x, param_x, state_x = iter(gen, param, state)
local r
repeat
state_x, r = call_if_not_empty(fun, gen_x(param_x, state_x))
until state_x == nil or not r
return state_x == nil
end

local any = function(fun, gen, param, state)
local gen_x, param_x, state_x = iter(gen, param, state)
local r
repeat
state_x, r = call_if_not_empty(fun, gen_x(param_x, state_x))
until state_x == nil or r
return not not r
end

local sum = function(gen, param, state)
local gen, param, state = iter(gen, param, state)
local s = 0
local r = 0
repeat
s = s + r
state, r = gen(param, state)
until state == nil
return s
end

local product = function(gen, param, state)
local gen, param, state = iter(gen, param, state)
local p = 1
local r = 1
repeat
p = p * r
state, r = gen(param, state)
until state == nil
return p
end

local min_cmp = function(m, n)
if n < m then return n else return m end
end

local max_cmp = function(m, n)
if n > m then return n else return m end
end

local min = function(gen, param, state)
local gen, param, state = iter(gen, param, state)
local state, m = gen(param, state)
if state == nil then
error("min: iterator is empty")
end

local cmp
if type(m) == "number" then
-- An optimization: use math.min for numbers
cmp = math.min
else
cmp = min_cmp
end

for _, r in gen, param, state do
m = cmp(m, r)
end
return m
end

local min_by = function(cmp, gen, param, state)
local gen_x, param_x, state_x = iter(gen, param, state)
local state_x, m = gen_x(param_x, state_x)
if state_x == nil then
error("min: iterator is empty")
end

for _, r in gen_x, param_x, state_x do
m = cmp(m, r)
end
return m
end

local max = function(gen, param, state)
local gen_x, param_x, state_x = iter(gen, param, state)
local state_x, m = gen_x(param_x, state_x)
if state_x == nil then
error("max: iterator is empty")
end

local cmp
if type(m) == "number" then
-- An optimization: use math.max for numbers
cmp = math.max
else
cmp = max_cmp
end

for _, r in gen_x, param_x, state_x do
m = cmp(m, r)
end
return m
end

local max_by = function(cmp, gen, param, state)
local gen_x, param_x, state_x = iter(gen, param, state)
local state_x, m = gen_x(param_x, state_x)
if state_x == nil then
error("max: iterator is empty")
end

for _, r in gen_x, param_x, state_x do
m = cmp(m, r)
end
return m
end

local totable = function(gen, param, state)
local gen_x, param_x, state_x = iter(gen, param, state)
local tab, key, val = {}
while true do
state_x, val = gen_x(param_x, state_x)
if state_x == nil then
break
end
table.insert(tab, val)
end
return tab
end

local tomap = function(gen, param, state)
local gen_x, param_x, state_x = iter(gen, param, state)
local tab, key, val = {}
while true do
state_x, key, val = gen_x(param_x, state_x)
if state_x == nil then
break
end
tab[key] = val
end
return tab
end

--------------------------------------------------------------------------------
-- Transformations
--------------------------------------------------------------------------------

local map_gen = function(param, state)
local gen_x, param_x, fun = param[1], param[2], param[3]
return call_if_not_empty(fun, gen_x(param_x, state))
end

local map = function(fun, gen, param, state)
local gen_x, param_x, state_x = iter(gen, param, state)
return map_gen, {gen_x, param_x, fun}, state_x
end

local enumerate_gen_call = function(state, i, state_x, ...)
if state_x == nil then
return nil
end
return {i + 1, state_x}, i, ...
end

local enumerate_gen = function(param, state)
local gen_x, param_x = param[1], param[2]
local i, state_x = state[1], state[2]
return enumerate_gen_call(state, i, gen_x(param_x, state_x))
end

local enumerate = function(gen, param, state)
local gen_x, param_x, state_x = iter(gen, param, state)
return enumerate_gen, {gen_x, param_x}, {0, state_x}
end

local intersperse_call = function(i, state_x, ...)
if state_x == nil then
return nil
end
return {i + 1, state_x}, ...
end

local intersperse_gen = function(param, state)
local x, gen_x, param_x = param[1], param[2], param[3]
local i, state_x = state[1], state[2]
if i % 2 == 1 then
return {i + 1, state_x}, x
else
return intersperse_call(i, gen_x(param_x, state_x))
end
end

-- TODO: interperse must not add x to the tail
local intersperse = function(x, gen, param, state)
local gen_x, param_x, state_x = iter(gen, param, state)
return intersperse_gen, {x, gen_x, param_x}, {0, state_x}
end

--------------------------------------------------------------------------------
-- Compositions
--------------------------------------------------------------------------------

local function zip_gen_r(param, state, state_new, ...)
if #state_new == #param / 2 then
return state_new, ...
end

local i = #state_new + 1
local gen_x, param_x = param[2 * i - 1], param[2 * i]
local state_x, r = gen_x(param_x, state[i])
-- print('i', i, 'state_x', state_x, 'r', r)
if state_x == nil then
return nil
end
table.insert(state_new, state_x)
return zip_gen_r(param, state, state_new, r, ...)
end

local zip_gen = function(param, state)
return zip_gen_r(param, state, {})
end

local zip = function(...)
local n = select('#', ...)
if n == 0 then
return nil_gen, nil, nil
end
local param = { [2 * n] = 0 }
local state = { [n] = 0 }

local i, gen_x, param_x, state_x
for i=1,n,1 do
local elem = select(n - i + 1, ...)
gen_x, param_x, state_x = iter_tab(elem)
param[2 * i - 1] = gen_x
param[2 * i] = param_x
state[i] = state_x
end

return zip_gen, param, state
end

local cycle_gen_call = function(param, state_x, ...)
if state_x == nil then
local gen_x, param_x, state_x0 = param[1], param[2], param[3]
return gen_x(param_x, deepcopy(state_x0))
end
return state_x, ...
end

local cycle_gen = function(param, state_x)
local gen_x, param_x, state_x0 = param[1], param[2], param[3]
return cycle_gen_call(param, gen_x(param_x, state_x))
end

local cycle = function(gen, param, state)
local gen_x, param_x, state_x = iter(gen, param, state)
return cycle_gen, {gen_x, param_x, state_x}, deepcopy(state_x)
end

-- call each other
local chain_gen_r1
local chain_gen_r2 = function(param, state, state_x, ...)
if state_x == nil then
local i = state[1]
i = i + 1
if i > #param / 3 then
return nil
end
local state_x = param[3 * i]
return chain_gen_r1(param, {i, state_x})
end
return {state[1], state_x}, ...
end

chain_gen_r1 = function(param, state)
local i, state_x = state[1], state[2]
local gen_x, param_x = param[3 * i - 2], param[3 * i - 1]
return chain_gen_r2(param, state, gen_x(param_x, state[2]))
end

local chain = function(...)
local n = select('#', ...)
if n == 0 then
return nil_gen, nil, nil
end

local param = { [3 * n] = 0 }
local i, gen_x, param_x, state_x
for i=1,n,1 do
local elem = select(i, ...)
gen_x, param_x, state_x = iter_tab(elem)
param[3 * i - 2] = gen_x
param[3 * i - 1] = param_x
param[3 * i] = state_x
end

return chain_gen_r1, param, {1, param[3]}
end

--------------------------------------------------------------------------------
-- Operators
--------------------------------------------------------------------------------

operator = {
----------------------------------------------------------------------------
-- Comparison operators
----------------------------------------------------------------------------
lt = function(a, b) return a < b end,
le = function(a, b) return a <= b end,
eq = function(a, b) return a == b end,
ne = function(a, b) return a ~= b end,
ge = function(a, b) return a >= b end,
gt = function(a, b) return a > b end,

----------------------------------------------------------------------------
-- Arithmetic operators
----------------------------------------------------------------------------
add = function(a, b) return a + b end,
div = function(a, b) return a / b end,
floordiv = function(a, b) return math.floor(a/b) end,
intdiv = function(a, b)
local q = a / b
if a >= 0 then return math.floor(q) else return math.ceil(q) end
end,
mod = function(a, b) return a % b end,
mul = function(a, b) return a * b end,
neq = function(a) return -a end,
unm = function(a) return -a end, -- an alias
pow = function(a, b) return a ^ b end,
sub = function(a, b) return a - b end,
truediv = function(a, b) return a / b end,

----------------------------------------------------------------------------
-- String operators
----------------------------------------------------------------------------
concat = function(a, b) return a..b end,
len = function(a) return #a end,
length = function(a) return #a end, -- an alias

----------------------------------------------------------------------------
-- Logical operators
----------------------------------------------------------------------------
land = function(a, b) return a and b end,
lor = function(a, b) return a or b end,
lnot = function(a) return not a end,
truth = function(a) return not not a end,
}

--------------------------------------------------------------------------------
-- module definitions
--------------------------------------------------------------------------------

local exports = {
----------------------------------------------------------------------------
-- Basic
----------------------------------------------------------------------------
iter = iter,
each = each,
for_each = each, -- an alias
foreach = each, -- an alias

----------------------------------------------------------------------------
-- Generators
----------------------------------------------------------------------------
range = range,
duplicate = duplicate,
xrepeat = duplicate, -- an alias
replicate = duplicate, -- an alias
tabulate = tabulate,
ones = ones,
zeros = zeros,
rands = rands,

----------------------------------------------------------------------------
-- Slicing
----------------------------------------------------------------------------
nth = nth,
head = head,
car = head, -- an alias
tail = tail,
cdr = tail, -- an alias
take_n = take_n,
take_while = take_while,
take = take,
drop_n = drop_n,
drop_while = drop_while,
drop = drop,
split = split,
split_at = split, -- an alias
span = split, -- an alias

----------------------------------------------------------------------------
-- Indexing
----------------------------------------------------------------------------
index = index,
index_of = index, -- an alias
elem_index = index, -- an alias
indexes = indexes,
indices = indexes, -- an alias
elem_indexes = indexes, -- an alias
elem_indices = indexes, -- an alias
find = find,

----------------------------------------------------------------------------
-- Filtering
----------------------------------------------------------------------------
filter = filter,
remove_if = filter, -- an alias
grep = grep,
partition = partition,

----------------------------------------------------------------------------
-- Reducing
----------------------------------------------------------------------------
foldl = foldl,
reduce = foldl, -- an alias
length = length,
is_null = is_null,
is_prefix_of = is_prefix_of,
all = all,
every = all, -- an alias
any = any,
some = any, -- an alias
sum = sum,
product = product,
min = min,
minimum = min, -- an alias
min_by = min_by,
minimum_by = min_by, -- an alias
max = max,
maximum = max, -- an alias
max_by = max_by,
maximum_by = max_by, -- an alias
totable = totable,
tomap = tomap,

----------------------------------------------------------------------------
-- Transformations
----------------------------------------------------------------------------
map = map,
enumerate = enumerate,
intersperse = intersperse,

----------------------------------------------------------------------------
-- Compositions
----------------------------------------------------------------------------
zip = zip,
cycle = cycle,
chain = chain,

----------------------------------------------------------------------------
-- Operators
----------------------------------------------------------------------------
operator = operator,
op = operator -- an alias
}

-- a special syntax sugar to export all functions to the global table
setmetatable(exports, {
__call = function(t)
for k, v in pairs(t) do _G[k] = v end
end,
})

return exports

Loading…
Cancel
Save