Skip to content

Instantly share code, notes, and snippets.

@bmwalters
Last active December 14, 2017 22:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bmwalters/28aa036e99b6e459be250a8ce3599af4 to your computer and use it in GitHub Desktop.
Save bmwalters/28aa036e99b6e459be250a8ce3599af4 to your computer and use it in GitHub Desktop.
comp.lua
local compresult
local COMP = {}
function COMP:__index(k)
return COMP[k] or self:addop("index", k)
end
function COMP:__call(...)
return self:addop("call", ...)
end
function COMP:__len()
return self:addop("len")
end
function COMP.__lt(lhs, rhs)
if getmetatable(lhs) == COMP then
compresult = lhs:addop("lt", rhs)
else
compresult = rhs:addop("gt", lhs)
end
end
function COMP:__concat(rhs)
return self:addop("concat", rhs)
end
function COMP:addop(type, ...)
self.ops[#self.ops + 1] = { type = type, params = {...} }
return self
end
function COMP:func()
local ops = self.ops
self.ops = {}
return function(value)
local lastvalue
for _, op in ipairs(ops) do
if op.type == "index" then
lastvalue = value
value = value[op.params[1]]
elseif op.type == "call" then
local params = {}
for i, p in ipairs(op.params) do params[i] = p end
if params[1] == self then params[1] = lastvalue end
value = value(table.unpack(params))
elseif op.type == "len" then
value = #value
elseif op.type == "lt" then
value = value < op.params[1]
elseif op.type == "gt" then
value = value > op.params[1]
elseif op.type == "concat" then
value = value .. op.params[1]
end
end
return value
end
end
debug.setmetatable(_G, {
__index = function(_, k)
if k:sub(1, 1) == "_" then
local oldval = _G[k:sub(2)]
_G[k:sub(2)] = setmetatable({ ops = {} }, COMP)
return setmetatable({}, {
__bor = function(_, rhs)
local f = (compresult or rhs):func()
compresult = nil
_G[k:sub(2)] = oldval
return f
end
})
end
end
})
dofile("comp.lua")
local FUNC = {}
FUNC.__index = FUNC
function FUNC:filter(f)
local out = {}
for _, v in ipairs(self) do
if f(v) then
out[#out + 1] = v
end
end
return setmetatable(out, FUNC)
end
function FUNC:map(f)
local out = {}
for i, v in ipairs(self) do
out[i] = f(v)
end
return setmetatable(out, FUNC)
end
function FUNC:foreach(f)
for _, v in ipairs(self) do
f(v)
end
end
function f(tab)
return setmetatable(tab, FUNC)
end
-- EXAMPLE
f{ { foo = "bar" }, { foo = "as" }, { foo = "baz" }, { foo = "qux" }, { foo = "cr" } }
:filter(_x | (#x.foo > 2))
:map(_x | x.foo:sub(1, 1))
:foreach(print)
dofile("comp.lua")
local transform = _x | x:upper() .. "!"
print(transform("hello world"))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment