Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ---------------------------------------------------------------------------
- ------------ Global Functional Utils v0.4
- ------------ Author: Trapcodien
- ---------------------------------------------------------------------------
- local serialization = require('serialization')
- _G.import = function(path)
- package.loaded[path] = nil
- return require(path)
- end
- local function simpleCompose(f, g)
- return function(...)
- return f(g(...))
- end
- end
- _G.fst = function(a, b) return a end
- _G.snd = function(a, b) return b end
- _G.pipe = function(f, g, ...)
- if g == nil then return f end
- local nextFn = simpleCompose(g, f)
- return pipe(nextFn, ...)
- end
- _G.compose = function(...)
- local reversedArgs = reverse(pack(...))
- return pipe(unpack(reversedArgs))
- end
- _G.flip = function(f)
- return curryN(2, function(a, b)
- return f(b, a)
- end)
- end
- _G.apply = function(...)
- local fns = pack(...)
- return function(...)
- return pipe(unpack(fns))(...)
- end
- end
- _G.applyTo = function(...)
- local args = pack(...)
- return function(...)
- return pipe(...)(unpack(args))
- end
- end
- _G.pack = table.pack
- _G.unpack = table.unpack
- _G.upper = string.upper
- _G.lower = string.lower
- _G.toUpper = string.upper
- _G.toLower = string.lower
- _G.null = setmetatable({}, { __tostring=function() return "null" end })
- -- used to stop forEach execution
- _G.stop = setmetatable({}, { __tostring=function() return "stop" end })
- _G.length = function(t)
- if isString(t) then return #t end
- local largerIndex = 0
- for k,v in pairs(t) do
- if type(k) == 'number' and k > largerIndex then
- largerIndex = k
- end
- end
- return largerIndex
- end
- _G.countItems = function(t)
- if isString(t) then return #t end
- local i = 0
- forEach(function()
- i = i + 1
- end, t)
- return i
- end
- local function concatTable(t1, t2)
- local t = {}
- for k,v in pairs(t1) do
- t[k] = v
- end
- local t1length = #t1
- for k2,v2 in pairs(t2) do
- local newKey = type(k2) == "number" and t1length + k2 or k2
- t[newKey] = v2
- end
- t.n = t1length + #t2
- return t
- end
- _G.curry = function(func, num_args)
- num_args = num_args or debug.getinfo(func, "u").nparams
- if num_args < 2 then return func end
- local function helper(argtrace, n)
- if n < 1 then
- return func(table.unpack(argtrace))
- else
- return function (...)
- return helper(concatTable(argtrace, pack(...)), n - select("#", ...))
- end
- end
- end
- return helper({}, num_args)
- end
- _G.curryN = function(num_args, func) return curry(func, num_args) end
- _G.flatten = function(t)
- local ret = {}
- for _, v in ipairs(t) do
- if type(v) == 'table' then
- for _, fv in ipairs(flatten(v)) do
- ret[#ret + 1] = fv
- end
- else
- ret[#ret + 1] = v
- end
- end
- return ret
- end
- _G.concat = curryN(2, function(t1, t2)
- if isString(t1) then return t1 .. t2 end
- return concatTable(t1, t2)
- end)
- local stringCount = function(substr, str)
- local i = 0
- local foundPos = 0
- while isNotNil(foundPos) do
- foundPos = string.find(str, substr, foundPos + 1)
- if isNotNil(foundPos) then
- i = i +1
- end
- end
- return i
- end
- _G.countWhen = curryN(2, function(predicate, t)
- local i = 0
- forEach(function(v, k)
- if predicate(v, k) then
- i = i + 1
- end
- end, t)
- return i
- end)
- _G.count = curryN(2, function(v, t)
- if isString(v) and isString(t) then return stringCount(v, t) end
- return countWhen(identical(v), t)
- end)
- local simpleMerge = function(t1, t2)
- local ret = clone(t1)
- forEach(function(v, k)
- ret[k] = v
- end, t2)
- return ret
- end
- _G.assign = function(t1, t2, ...)
- if isNil(t2) then return t1 end
- local merged = simpleMerge(t1, t2)
- return assign(merged, ...)
- end
- _G.mergeTo = curryN(2, simpleMerge)
- _G.merge = mergeTo
- _G.withDefault = flip(merge)
- _G.complement = function(predicate)
- return function(...)
- return not predicate(...)
- end
- end
- _G.ternary = curryN(3, function(bool, v1, v2)
- if bool then
- return v1
- else
- return v2
- end
- end)
- _G.Nil = function() return nil end
- _G.toNil = Nil
- _G.Table = pack
- _G.toTable = Table
- _G.String = tostring
- _G.toString = String
- _G.Number = function(x)
- if isBoolean(x) then
- return ternary(x, 1, 0)
- elseif isNil(x) then
- return 0
- end
- return tonumber(x)
- end
- _G.toNumber = Number
- _G.isStringIsNumber = function(v)
- if not isString(v) then return false end
- return isNumber(Number(v))
- end
- _G.max = curryN(2, function(a, b)
- return math.max(a, b)
- end)
- _G.min = curryN(2, function(a, b)
- return math.min(a, b)
- end)
- _G.abs = math.max
- _G.negate = function(x) return -x end
- _G.of = function(v) return {v} end
- _G.isWhitespace = function(v)
- return v == ' ' or v == '\t' or v == '\n'
- end
- _G.isNotWhitespace = complement(isWhitespace)
- -- ACCESSORS/UPDATERS
- _G.replaceCharAt = curryN(3, function(pos, c, str)
- if pos < 0 then
- pos = #str + 1 + abs(pos)
- end
- return string.sub(str, 1, pos - 1) .. c .. string.sub(str, pos + 1)
- end)
- _G.removeCharAt = curryN(2, function(pos, str)
- return replaceCharAt(pos, '', str)
- end)
- _G.insertCharAt = curryN(3, function(pos, c, str)
- if pos < 0 then
- pos = #str + 2 + abs(pos)
- elseif pos == 0 then
- pos = 1
- end
- return string.sub(str, 0, pos - 1) .. c .. string.sub(str, pos)
- end)
- _G.prop = curryN(2, function(k, t)
- if isString(t) then return string.sub(t, k, k) end
- if isNotTable(t) then return nil end
- return t[k]
- end)
- _G.propOr = curryN(3, function(fallbackValue, k, t)
- return prop(k, t) or fallbackValue
- end)
- _G.setProp = curryN(3, function(k, v, t)
- if isString(t) then
- return replaceCharAt(k, v, t)
- end
- if isNotTable(t) then return t end
- local newTable = clone(t)
- newTable[k] = v
- return newTable
- end)
- _G.setNonNilProps = curryN(3, function(k, v, t)
- if isString(t) and isNotNil(prop(k, t)) then
- return replaceCharAt(k, v, t)
- end
- if isNotTable(t) then return t end
- if isNil(t[k]) then return t end
- return setProp(k, v, t)
- end)
- _G.removeProp = curryN(2, function(k, t)
- return omit(k)(t)
- end)
- _G.updateProp = curryN(3, function(k, f, t)
- return setProp(k, f(prop(k, t)), t)
- end)
- _G.updateNonNilProp = curryN(3, function(k, f, t)
- local v = prop(k, t)
- if isNil(v) then return t end
- return setProp(k, f(v), t)
- end)
- _G.path = function(...)
- local ks = pack(...)
- local firstKey = head(ks)
- return function(t)
- if isNil(t) or isNil(firstKey) then return t end
- return path(unpack(tail(ks))) (prop(firstKey, t))
- end
- end
- _G.pathOr = function(fallbackValue, ...)
- local args = pack(...)
- return function(t)
- return path(unpack(args))(t) or fallbackValue
- end
- end
- -------------- TODO
- _G.setPath = nil
- _G.setNonNilPath = nil
- _G.removePath = nil
- _G.updatePath = nil
- _G.updateNonNilPath = nil
- _G.propCompare = nil
- _G.pathCompare = nil
- _G.propEq = nil
- _G.pathEq = nil
- _G.propIdentical = nil
- _G.pathIdentical = nil
- -------------------
- _G.keys = function(t)
- return map(snd, t)
- end
- _G.omit = function(...)
- local keys = pack(...)
- return function(t)
- return reject(function(value, key)
- local foundIndex = findKey(identical(key), keys)
- return isNotNil(foundIndex)
- end, t)
- end
- end
- _G.pick = function(...)
- local keys = pack(...)
- return function(t)
- return filter(function(value, key)
- local foundIndex = findKey(identical(key), keys)
- return isNotNil(foundIndex)
- end, t)
- end
- end
- _G.append = curryN(2, function(v, t)
- return concat(t, {v})
- end)
- _G.prepend = curryN(2, function(v, t)
- return concat({v}, t)
- end)
- _G.take = curryN(2, function(n, t)
- if isString(t) then return string.sub(t, 0, n) end
- local ret = {}
- local taken = 0
- forEach(function(v, k)
- if taken >= n then return stop end
- if isNumber(k) then
- ret[k] = v
- taken = taken + 1
- end
- end, t)
- return ret
- end)
- _G.drop = curryN(2, function(n, t)
- if n <= 0 then return t end
- if isString(t) then
- return string.sub(t, n + 1)
- end
- local ret = {}
- local dropped = 0
- local i = 1
- forEach(function(v, k)
- if dropped >= n then
- ret[i] = v
- i = i + 1
- else
- dropped = dropped + 1
- end
- end, t)
- return ret
- end)
- _G.takeLast = curryN(2, function(n, t)
- if isString(t) then
- return string.sub(t, -n)
- end
- local size = length(compact(t))
- local toDrop = math.max(0, size - n)
- return drop(toDrop, t)
- end)
- _G.dropLast = curryN(2, function(n, t)
- local size = length(compact(t))
- local toTake = math.max(0, size - n)
- return take(toTake, t)
- end)
- local stringDropUntil = function(predicate, str)
- local ret = ''
- local shouldDrop = true
- forEach(function(c, k)
- if shouldDrop then
- shouldDrop = not predicate(c, k)
- end
- if not shouldDrop then
- ret = ret .. c
- end
- end, str)
- return ret
- end
- _G.dropUntil = curryN(2, function(predicate, t)
- if isString(t) then return stringDropUntil(predicate, t) end
- local ret = {}
- local shouldDrop = true
- local i = 1
- forEachIndex(function(v, k)
- if shouldDrop then
- shouldDrop = not predicate(v, k)
- end
- if not shouldDrop then
- ret[i] = v
- i = i + 1
- end
- end, t)
- return ret
- end)
- local stringTakeUntil = function(predicate, str)
- local ret = ''
- local shouldTake = true
- forEach(function(c, k)
- shouldTake = not predicate(c, k)
- if not shouldTake then return stop end
- ret = ret .. c
- end, str)
- return ret
- end
- _G.takeUntil = curryN(2, function(predicate, t)
- if isString(t) then return stringTakeUntil(predicate, t) end
- local ret = {}
- local i = 1
- local shouldTake = true
- forEachIndex(function(v, k)
- shouldTake = not predicate(v, k)
- if not shouldTake then return stop end
- ret[i] = v
- i = i + 1
- end, t)
- return ret
- end)
- _G.dropLastUntil = curryN(2, function(predicate, t)
- return applyTo(t)(
- reverse,
- dropUntil(predicate),
- reverse
- )
- end)
- _G.takeLastUntil = curryN(2, function(predicate, t)
- return applyTo(t)(
- reverse,
- takeUntil(predicate),
- reverse
- )
- end)
- _G.head = function(t)
- if isString(t) then return prop(1, t) end
- local foundHead = nil
- forEach(function(v)
- foundHead = v
- return stop
- end, t)
- return foundHead
- end
- _G.first = head
- _G.tail = drop(1)
- _G.last = function(t)
- if isString(t) then return string.sub(t, -1) end
- return t[length(t)]
- end
- -------- STRING UTILS ----------
- _G.trimStart = dropUntil(isNotWhitespace)
- _G.trimEnd = dropLastUntil(isNotWhitespace)
- _G.trim = pipe(trimStart, trimEnd)
- _G.join = curryN(2, function(sep, t)
- return table.concat(t, sep)
- end)
- local simpleSplit = function(sep, str)
- if str == "" then return nil end
- local sepPos, nextPos = string.find(str, sep)
- if isNil(nextPos) then return str end
- local firstWord = string.sub(str, 1, sepPos - 1)
- local secondWord = string.sub(str, nextPos + 1)
- return firstWord, secondWord
- end
- _G.split = curryN(2, function(sep, str)
- local ret = {}
- local restString = str
- while isNotEmpty(restString) do
- local firstWord, secondWord = simpleSplit(sep, restString)
- if isNotNil(firstWord) then
- table.insert(ret, firstWord)
- end
- restString = secondWord
- end
- return ret
- end)
- _G.startsWith = curryN(2, function(substr, str)
- return take(#substr, str) == substr
- end)
- _G.endWith = curryN(2, function(substr, str)
- return takeLast(#substr, str) == substr
- end)
- _G.contains = curryN(2, function(value, t)
- if isString(value) and isString(t) then
- return Boolean(string.find(t, value))
- end
- local valueFound = false
- forEach(function(v)
- if value == v then
- valueFound = true
- return stop
- end
- end, t)
- return valueFound
- end)
- _G.oneOf = flip(contains)
- -- TYPE PREDICATES
- _G.is = curryN(2, function(givenType, value)
- return type(value) == givenType
- end)
- _G.isNot = curryN(2, function(givenType, value)
- return not (type(value) == givenType)
- end)
- _G.isString = is('string')
- _G.isTable = is('table')
- _G.isNumber = is('number')
- _G.isBoolean = is('boolean')
- _G.isNotString = isNot('string')
- _G.isNotTable = isNot('table')
- _G.isNotNumber = isNot('number')
- _G.isNotBoolean = isNot('boolean')
- _G.isNull = function(v) return v == null end
- _G.isNotNull = complement(isNull)
- _G.isNil = function(v) return v == nil or v == null end
- _G.isNotNil = complement(isNil)
- _G.Boolean = function(v)
- local isFalsy = isNil(v) or v == '' or v == 0 or v == false
- return not isFalsy
- end
- _G.isTruthy = Boolean
- _G.isFalsy = complement(Boolean)
- _G.isEmpty = function(v)
- if v == '' then return true end
- if isNil(v) then return true end
- if isTable(v) then
- local iterated = false
- forEach(function(x)
- iterated = true
- return stop
- end, v)
- return not iterated
- end
- return false
- end
- _G.isNotEmpty = complement(isEmpty)
- _G.isHuge = function(x) return x == math.huge end
- _G.isNotHuge = complement(isHuge)
- _G.byte = function(c)
- return string.byte(c)
- end
- _G.char = function(code)
- return string.char(code)
- end
- _G.isStringIsNumeric = function(v)
- if not isString(v) then return false end
- return isStringIsNumber(head(v))
- end
- _G.lt = curryN(2, function(a, b)
- return b < a
- end)
- _G.lte = curryN(2, function(a, b)
- return b <= a
- end)
- _G.gt = curryN(2, function(a, b)
- return b > a
- end)
- _G.gte = curryN(2, function(a, b)
- return b >= a
- end)
- _G.isZero = function(x) return x == 0 end
- _G.isNotZero = complement(isZero)
- -- BASIC LOGIC
- _G.identical = curryN(2, function(a, b) return a == b end)
- _G.notIdentical = curryN(2, function(a, b) return not(a == b) end)
- _G.isTrue = identical(true)
- _G.isNotTrue = complement(isTrue)
- _G.isFalse = identical(false)
- _G.isNotFalse = complement(isFalse)
- _G.xor = curryN(2, function(a, b)
- return (a == true and b == false) or (a == false and b == true)
- end)
- _G.ifElse = curryN(3, function(predicate, transformerThen, transformerElse)
- return function(...)
- if predicate(...) then
- return transformerThen(...)
- else
- return transformerElse(...)
- end
- end
- end)
- _G.when = curryN(2, function(predicate, transformerThen)
- return function(...)
- return ifElse(predicate, transformerThen, identity)(...)
- end
- end)
- _G.defaultTo = curryN(2, function(fallbackValue, v)
- if isNotNil(v) then return v end
- return fallbackValue
- end)
- _G.equalsBy = curryN(2, function(comparator, a, b)
- if (a == b) then return true end
- if isNotTable(a) or isNotTable(b) then return false end
- local isShallowEquals = true
- local iterated = false
- forEach(function(value, key)
- iterated = true
- if not comparator(value, b[key]) then
- isShallowEquals = false
- return stop
- end
- end, a)
- forEach(function(value, key)
- iterated = true
- if not comparator(value, a[key]) then
- isShallowEquals = false
- return stop
- end
- end, b)
- if not iterated then return true end
- return isShallowEquals
- end)
- _G.notEqualsBy = curryN(2, function(comparator, a, b)
- return not equalsBy(comparator, a, b)
- end)
- _G.equals = equalsBy(identical)
- _G.notEquals = notEqualsBy(identical)
- _G.deepEquals = curryN(2, function(a, b)
- return equalsBy(deepEquals, a, b)
- end)
- _G.notDeepEquals = curryN(2, function(a, b)
- return not equalsBy(notDeepEquals, a, b)
- end)
- _G.both = curryN(3, function(predicate1, predicate2, value)
- return predicate1(value) and predicate2(value)
- end)
- _G.either = curryN(3, function(predicate1, predicate2, value)
- return predicate1(value) or predicate2(value)
- end)
- _G.allPass = curryN(2, function(predicates, value)
- local reducer = function(acc, p) return acc and p(value) end
- return reduce(reducer, true, predicates)
- end)
- _G.anyPass = curryN(2, function(predicates, value)
- local reducer = function(acc, p) return acc or p(value) end
- return reduce(reducer, false, predicates)
- end)
- _G.identity = function(x) return x end
- _G.noop = function() end
- _G.always = function(...)
- local args = pack(...)
- return function()
- return unpack(args)
- end
- end
- _G.tap = function(f)
- return function(...)
- f(...)
- return ...
- end
- end
- _G.log = tap(print)
- _G.add = curryN(2, function(a, b) return a + b end)
- _G.sub = curryN(2, function(a, b) return b - a end)
- _G.inc = add(1)
- _G.dec = add(-1)
- local a = byte('a')
- local A = byte('A')
- local z = byte('z')
- local Z = byte('Z')
- _G.isAlphaMin = function(v)
- if not isString(v) then return false end
- local code = byte(v)
- return code >= a and code <= z
- end
- _G.isAlphaMaj = function(v)
- if not isString(v) then return false end
- local code = byte(v)
- return code >= A and code <= Z
- end
- _G.isAlpha = either(isAlphaMin, isAlphaMaj)
- _G.isAlphaNum = either(isStringIsNumeric, isAlpha)
- -- TABLE FUNCTIONS
- _G.compact = function(t)
- if isString(t) then return t end
- local ret = {}
- local i = 0
- forEach(function(v, k)
- if isNil(v) then return nil end
- if isNumber(k) then
- i = i + 1
- ret[i] = v
- else
- ret[k] = v
- end
- end, t)
- if t.n then ret.n = i end
- return ret
- end
- _G.reverse = function(t)
- if isString(t) then return string.reverse(t) end
- local ret = {}
- ret.n = t.n
- objForEach(function(v, k)
- ret[k] = v
- end, t)
- local tlen = length(t)
- local i = 1
- while i <= tlen do
- ret[tlen - (i - 1)] = t[i]
- i = i + 1
- end
- return ret
- end
- _G.forEach = curryN(2, function(f, t)
- if isString(t) then
- for i=1, #t do
- local c = string.sub(t, i, i)
- if f(c, i) == stop then return nil end
- end
- return nil
- end
- for k, v in pairs(t) do
- if notIdentical(k, 'n') then
- if f(v, k) == stop then return nil end
- end
- end
- end)
- _G.forEachIndex = curryN(2, function(f, t)
- if isString(t) then
- return forEach(f, t)
- end
- for k, v in pairs(t) do
- if (isNumber(k)) then
- if f(v, k) == stop then return nil end
- end
- end
- end)
- _G.objForEach = curryN(2, function(f, t)
- for k, v in pairs(t) do
- if isNotNumber(k) then
- if f(v, k) == stop then return nil end
- end
- end
- end)
- _G.forEachRight = curryN(2, function(f, t)
- if isString(t) then
- for i=#t,1,-1 do
- local c = string.sub(t, i, i)
- if f(c, i) == stop then return nil end
- end
- return nil
- end
- t = compact(t)
- local tlen = length(t)
- for i=tlen,1,-1 do
- if f(t[i], i) == stop then return nil end
- end
- end)
- _G.forEachLast = forEachRight
- _G.forEachIndexRight = curryN(2, function(f, t)
- return forEachRight(function(v, k)
- return f(k)
- end, t)
- end)
- _G.forEachIndexLast = forEachIndexRight
- local mapString = function(f, str)
- local ret = ''
- forEach(function(v)
- ret = ret .. f(v)
- end, str)
- return ret
- end
- _G.map = curryN(2, function(f, t)
- if isString(t) then return mapString(f, t) end
- local ret = {}
- ret.n = t.n
- forEach(function(v, k)
- ret[k] = f(v, k)
- end, t)
- return ret
- end)
- _G.deepMap = curryN(2, function(f, t)
- if isTable(t) then return map(deepMap(f), t) end
- return f(t)
- end)
- local filterString = function(predicate, str)
- local ret = ''
- forEach(function(value, key)
- if predicate(value, key) then
- ret = ret .. value
- end
- end, str)
- return ret
- end
- _G.filter = curryN(2, function(predicate, t)
- if isString(t) then return filterString(predicate, t) end
- local ret = {}
- forEach(function(value, key)
- if predicate(value, key) then
- ret[key] = value
- end
- end, t)
- if type(t.n) == 'number' then
- ret.n = length(ret)
- end
- return compact(ret)
- end)
- _G.reject = curryN(2, function(predicate, t)
- return filter(complement(predicate), t)
- end)
- _G.reduce = curryN(3, function(reducer, initialAcc, t)
- local acc = initialAcc
- forEach(function(value)
- acc = reducer(acc, value)
- end, t)
- return acc
- end)
- _G.find = curryN(2, function(predicate, t)
- local foundValue = nil
- forEach(function(v, k)
- if predicate(v, k) then
- foundValue = v;
- return stop
- end
- end, t)
- return foundValue
- end)
- _G.findKey = curryN(2, function(predicate, t)
- local foundKey = nil
- forEach(function(v, k)
- if predicate(v, k) then
- foundKey = k
- return stop
- end
- end, t)
- return foundKey
- end)
- _G.findByKey = curryN(2, function(predicate, t)
- return find(function(v, k)
- return predicate(k)
- end, t)
- end)
- _G.clone = map(identity)
- _G.deepClone = deepMap(identity)
- local function dumpTable(tbl, indent)
- if not (type(tbl) == 'table') then
- print(tbl)
- return nil
- end
- if not indent then indent = 0 end
- for k, v in pairs(tbl) do
- formatting = string.rep(" ", indent) .. k .. ": "
- if type(v) == "table" then
- print(formatting)
- dumpTable(v, indent+1)
- elseif type(v) == 'boolean' then
- print(formatting .. tostring(v))
- else
- print(formatting .. v)
- end
- end
- end
- _G.dump = function(...)
- local args = pack(...)
- forEach(function(arg)
- dumpTable(arg)
- end, args)
- return ...
- end
- _G.serialize = serialization.serialize
- _G.unserialize = serialization.unserialize
- _G.parse = unserialize
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement