-- Localize globals local modlib, unpack, select, setmetatable = modlib, unpack, select, setmetatable -- Set environment local _ENV = {} setfenv(1, _ENV) no_op = function() end function curry(func, ...) local args = { ... } return function(...) return func(unpack(args), ...) end end function curry_tail(func, ...) local args = { ... } return function(...) return func(unpack(modlib.table.concat({...}, args))) end end function curry_full(func, ...) local args = { ... } return function() return func(unpack(args)) end end function args(...) local args = { ... } return function(func) return func(unpack(args)) end end function value(val) return function() return val end end function values(...) local args = { ... } return function() return unpack(args) end end function memoize(func) return setmetatable({}, { __index = function(self, key) local value = func(key) self[key] = value return value end, __call = function(self, arg) return self[arg] end, __mode = "k" }) end -- Does not use select magic, stops at the first nil value function aggregate(binary_func, total, ...) if total == nil then return end local function _aggregate(value, ...) if value == nil then return end total = binary_func(total, value) return _aggregate(...) end _aggregate(...) return total end function override_chain(func, override) return function(...) func(...) return override(...) end end --+ Calls func using the provided arguments, deepcopies all arguments function call_by_value(func, ...) return func(unpack(modlib.table.deepcopy{...}, 1, select("#", ...))) end -- Functional wrappers for Lua's builtin metatable operators (arithmetic, concatenation, length, comparison, indexing, call) function add(a, b) return a + b end function mul(a, b) return a * b end function div(a, b) return a / b end function mod(a, b) return a % b end function pow(a, b) return a ^ b end function unm(a) return -a end function concat(a, b) return a .. b end function len(a) return #a end function eq(a, b) return a == b end function lt(a, b) return a < b end function le(a, b) return a <= b end function index(object, key) return object[key] end function newindex(object, key, value) object[key] = value end function call(object, ...) object(...) end -- Functional wrappers for logical operators, suffixed with _ for syntactical convenience function not_(a) return not a end _ENV["not"] = not_ function and_(a, b) return a and b end _ENV["and"] = and_ function or_(a, b) return a or b end _ENV["or"] = or_ -- Export environment return _ENV