Last active
March 28, 2025 04:11
-
-
Save Kaleidosium/1af5454e7050c48db35e3ced8d7fac31 to your computer and use it in GitHub Desktop.
Functional Programming utilities for YueScript
This file contains hidden or 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
-- https://stackoverflow.com/a/11671820 | |
-- e.g: map({1,2,3,4}, (o) -> o * 2) -> {2,4,6,8} | |
export map = (tbl, fn) -> | |
out = {} | |
for k, v in pairs tbl | |
out[k] = fn v | |
return out | |
-- https://gist.github.com/FGRibreau/3790217 | |
-- e.g: filter({"a","b","c","d"}, (o, k, i) -> o >= "c") -> { [3]: "c", [4]: "d" } | |
export filter = (tbl, fn) -> | |
out = {} | |
for k, v in pairs tbl | |
if fn v, k, tbl then out[k] = v | |
return out | |
-- Left fold (processes list from left to right) | |
-- e.g: foldl({1,2,3,4}, 0, (acc, x) -> acc + x) -> 10 | |
export foldl = (tbl, initial, fn) -> | |
return initial if not tbl or #tbl == 0 | |
acc = initial | |
for i = 1, #tbl | |
acc = fn acc, tbl[i] | |
return acc | |
-- Right fold (processes list from right to left) | |
-- e.g: foldr({1,2,3,4,5}, 1, (acc, x) -> acc * x) -> 120 | |
export foldr = (tbl, initial, fn) -> | |
return initial if not tbl or #tbl == 0 | |
acc = initial | |
for i = #tbl, 1, -1 | |
acc = fn acc, tbl[i] | |
return acc | |
-- reduce is an alias for foldr | |
export reduce = (tbl, init, fn) -> | |
return foldr(tbl, init, fn) | |
-- foldl1/foldr1 take the first/last element as the initial value -- | |
-- e.g: foldl1({1,2,3,4,5}, (acc, x) -> if acc > x then acc else x) -> 5 | |
export foldl1 = (tbl, fn) -> | |
return nil if not tbl or #tbl == 0 | |
return tbl[1] if #tbl == 1 | |
rest = [tbl[i] for i = 2, #tbl] | |
return foldl rest, tbl[1], fn | |
-- e.g: foldr1({1,2,3,4,5}, (acc, x) -> if acc < x then acc else x) -> 1 | |
export foldr1 = (tbl, fn) -> | |
return nil if not tbl or #tbl == 0 | |
return tbl[#tbl] if #tbl == 1 | |
init = tbl[#tbl] | |
rest = [tbl[i] for i = 1, #tbl - 1] | |
return foldr rest, init, fn | |
-- e.g: printf = compose(io.write, string.format) | |
-- -> function(...) return io.write(string.format(unpack(arg))) end | |
export compose = (f, g) -> | |
return (...) -> f(g(...)) | |
-- https://lua-stdlib.github.io/functional/modules/functional.html#bind | |
-- Partially apply a function with arguments at specified positions | |
-- arg_t is a table where keys are argument positions and values are the bound values | |
-- e.g: cube = bind(math.pow, {[2]: 3}) -- cube(2) returns 2^3 = 8 | |
export bind = (fn, arg_t) -> | |
return (...) -> | |
args = {...} | |
-- Create a copy of the bound arguments | |
bound_args = {} | |
for k, v in pairs arg_t | |
bound_args[k] = v | |
-- Fill in the unbound arguments | |
arg_index = 1 | |
for i = 1, math.max(#args, table.maxn(bound_args)) | |
if not bound_args[i] | |
bound_args[i] = args[arg_index] | |
arg_index += 1 | |
return fn(unpack(bound_args)) | |
-- https://lua-stdlib.github.io/functional/modules/functional.html#curry | |
-- Curry a function with the specified number of arguments | |
export curry = (fn, n) -> | |
if n == 0 then return fn | |
return (x) -> | |
return curry(bind(fn, {x}), n - 1) | |
-- Ruby-style zip | |
-- e.g: zip({1,2,3}, {"a","b","c"}) -> {{1,"a"}, {2,"b"}, {3,"c"}} | |
export zip = (a, b) -> | |
result = {} | |
for i = 1, math.min(#a, #b) | |
result[i] = {a[i], b[i]} | |
return result |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment