Created
December 11, 2018 15:59
-
-
Save kigiri/0c4e43893faa54ad5987e788a28a7dcd to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local function empty(tbl) | |
if type(tbl) == 'string' then return #tbl == 0 end | |
if type(tbl) ~= 'table' then return true end | |
if #tbl ~= 0 then return false end | |
for k, v in pairs(tbl) do return false end | |
return true | |
end | |
local function len(tbl) | |
if type(tbl) ~= 'table' then return 0 end | |
local count = 0 | |
for k, v in pairs(tbl) do count = count + 1 end | |
return count | |
end | |
local function concat1(a, b) | |
for _, v in ipairs(b) do table.insert(a, v) end | |
return a | |
end | |
local function concat(...) | |
t = {} | |
for _, v in ipairs({...}) do concat1(t, v) end | |
return t | |
end | |
local function assign1(a, b) | |
for k, v in pairs(b) do a[k] = v end | |
return a | |
end | |
local function assign(t, ...) | |
for _, v in ipairs({...}) do assign1(t, v) end | |
return t | |
end | |
local function spread(...) return assign({}, ...) end | |
local function curryFlip(action) | |
return function (func) return function (...) return action(..., func) end end | |
end | |
function eval(strFunc) | |
local func, err = loadstring('return function (x) return '..strFunc..' end') | |
if err then print(err) end | |
return func() | |
end | |
local function map(tbl, func) | |
if type(func) == 'string' then func = eval(func) end | |
local t = {} | |
for k, v in pairs(tbl) do t[k] = func(v, k) end | |
return t | |
end | |
local function get(tbl, key) return tbl[key] end | |
local function filter(tbl, func) | |
if type(func) == 'string' then func = eval(func) end | |
local t = {} | |
for k, v in pairs(tbl) do if func(v) then t[k] = v end end | |
return t | |
end | |
local function fold(tbl, acc, func) | |
if type(func) == 'string' then func = eval(func) end | |
for k, v in pairs(tbl) do acc = func(acc, v, k) end | |
return acc | |
end | |
local function reduce(tbl, func) | |
if type(func) == 'string' then func = eval(func) end | |
if (empty(tbl)) then error('reduce was called with an empty table') end | |
local head = table.remove(tbl, 1) | |
return fold(tbl, head, func) | |
end | |
local function join(tbl, sep) | |
if type(tbl) ~= 'table' then return '' end | |
return table.concat(tbl, sep or '') | |
end | |
local function nTbl(n) | |
local t = {} | |
for i = 1, n do t[i] = i end | |
return t | |
end | |
local function keys(tbl) | |
local t = {} | |
for k, _ in pairs(list) do table.insert(t, k) end | |
return t | |
end | |
local function uniq(tbl) | |
local t = {} | |
for _, l in ipairs(list) do | |
t[l] = true | |
end | |
return keys(t) | |
end | |
local function flat(tbl) | |
local t = {} | |
for _, v in ipairs(tbl) do | |
if not type(v) == 'table' then | |
table.insert(t, v) | |
else | |
for _, vv in ipairs(v) do | |
table.insert(t, vv) | |
end | |
end | |
end | |
return t | |
end | |
local T = {} | |
setmetatable(T, { | |
__call = function (self, ...) | |
local args = {...} | |
if #args == 0 then return setmetatable({}, T) end | |
if #args == 1 then | |
local arg = args[1] | |
if not arg then return setmetatable({}, T) end | |
if type(arg) == 'table' then return setmetatable(arg, T) end | |
return setmetatable({arg}, T) | |
end | |
return setmetatable(args, T) | |
end | |
}) | |
-- T.__len = | |
-- T.__tostring = | |
T.__concat = function (self, tbl) | |
--print('lhs', self) | |
--print('rhs', tbl) | |
return setmetatable(assign1(assign1({}, self), tbl), T) | |
end | |
local function register(proto, name, func) | |
if not proto.__index then proto.__index = { new = proto } end | |
proto.__index[name] = func | |
end | |
local function registerChained(proto, name, func) | |
return register(proto, name, function (...) | |
return setmetatable(func(...), proto) | |
end) | |
end | |
local g = T({ abc = 'abc' })..T({ def = 'def' }) | |
for k, v in pairs(g) do print(k, v) end | |
--local g2 = g:map(function (n) return n..tostring(12) end) | |
--for k, v in pairs(g2) do print(k, v) end | |
function slice(tbl, first, last, step) | |
local size = #tbl | |
if first < 0 then first = size + first end | |
if last < 0 then last = size + last end | |
local t = {} | |
for i = first or 1, last or size, step or 1 do | |
table.insert(t, tbl[i]) | |
end | |
return t | |
end | |
local mapper = curryFlip(map) | |
local filterer = curryFlip(filter) | |
local folder = curryFlip(fold) | |
local reducer = curryFlip(fold) | |
local joiner = curryFlip(join) | |
local getter = curryFlip(get) | |
registerChained(T, 'map', map) | |
registerChained(T, 'fold', fold) | |
registerChained(T, 'slice', slice) | |
registerChained(T, 'filter', filter) | |
registerChained(T, 'reduce', reduce) | |
register(T, 'join', join) | |
register(T, 'set', function (self, key, value) | |
return self..{ [key] = value } | |
end) | |
for i,v in ipairs(nTbl(20)) do | |
print(i,v) | |
end | |
print(T(nTbl(20)) | |
:slice(2, -2) | |
:filter('x % 2 == 0') | |
:map('x + 10') | |
:join('-')) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment