Skip to content

Instantly share code, notes, and snippets.

@rjeschke
Created January 4, 2012 21:53
Show Gist options
  • Save rjeschke/1562374 to your computer and use it in GitHub Desktop.
Save rjeschke/1562374 to your computer and use it in GitHub Desktop.
Weel functional programming library (clojure-like)
/*
* Experimental clojure-like functional programming library
*/
func map(fn, ls)
local ret = {};
if !ls || !fn then
return ret;
end
foreach v in ls do
ret[] = fn(v);
end
return ret;
end
func reduce(fn, ls)
if !fn || !ls then
return null;
end
if size(ls) == 1 then
return ls[0];
end
local v = fn(ls[0], ls[1]);
for i = 2, size(ls) - 1 do
v = fn(v, ls[i]);
end
return v;
end
func reduce(fn, v, ls)
if !fn || !ls then
return null;
end
if size(ls) == 1 then
return ls[0];
end
for i = 0, size(ls) - 1 do
v = fn(v, ls[i]);
end
return v;
end
private func _flatten(ls, ret)
if !ls then
return ret;
end
if mapIsList(ls) then
for i = 0, size(ls) - 1 do
local t = ls[i];
if isMap(t) then
ret = _flatten(t, ret);
else
ret[] = t;
end
end
else
foreach k, v in ls do
ret[] = k;
if isMap(v) then
ret = _flatten(v, ret);
else
ret[] = v;
end
end
end
return ret;
end
func flatten(ls)
return _flatten(ls, {});
end
func range(max)
local ret = {};
for i = 0, max - 1 do
ret[] = i;
end
return ret;
end
func range(min, max)
local ret = {};
for i = min, max - 1 do
ret[] = i;
end
return ret;
end
func interleave(ls0, ls1)
local ret = {};
if !ls0 || !ls1 then
return ret;
end
for i = 0, min(size(ls0), size(ls1)) - 1 do
ret[] = ls0[i];
ret[] = ls1[i];
end
return ret;
end
func hashMap(ls)
local ret = {};
if !ls then
return ret;
end
for i = 0, (size(ls) >> 1) - 1 do
ret[ls[i * 2]] = ls[i * 2 + 1];
end
return ret;
end
func distinct(ls)
local ret = {};
if !ls then
return ret;
end
for i = 0, size(ls) - 1 do
ret[ls[i]] = ls[i];
end
return mapToList(ret);
end
func filter(fn, ls)
local ret = {};
if !fn || !ls then
return ret;
end
for i = 0, size(ls) - 1 do
if fn(ls[i]) then
ret[] = ls[i];
end
end
return ret;
end
func first(ls)
if !ls || !size(ls) then
return null;
end
return ls[0];
end
func last(ls)
if !ls || !size(ls) then
return null;
end
return ls[size(ls) - 1];
end
func take(n, ls)
local ret = {};
if !ls then
return ret;
end
for i = 0, min(size(ls), n) - 1 do
ret[] = ls[i];
end
return ret;
end
func rest(ls)
local ret = {};
if !ls || !size(ls) then
return ret;
end
for i = 1, size(ls) - 1 do
ret[] = ls[i];
end
return ret;
end
func drop(n, ls)
local ret = {};
if !ls || !size(ls) then
return ret;
end
local s = max(0, size(ls) - n);
for i = s, size(ls) - 1 do
ret[] = ls[i];
end
return ret;
end
func concat(ls0, ls1)
local ret = {};
if ls0 then
for i = 0, size(ls0) - 1 do
ret[] = ls0[i];
end
end
if ls1 then
for i = 0, size(ls1) - 1 do
ret[] = ls1[i];
end
end
return ret;
end
func interpose(v, ls)
local ret = {};
if !ls then
return ret;
end
ret[] = ls[0];
for i = 1, size(ls) - 1 do
ret[] = v;
ret[] = ls[i];
end
return ret;
end
// No var-args yet, so we need a list
func apply(fn, ls)
if !ls then
return null;
end
if size(ls) == 1 then
local f = funcFind(funcName(fn), 1);
return f ? f(ls[0]) : null;
end
local v = fn(ls[0], ls[1]);
for i = 2, size(ls) - 1 do
v = fn(v, ls[i]);
end
return v;
end
func str(a)
return toStr(a);
end
func str(a, b)
return toStr(a)..toStr(b);
end
func seq(v)
if isString(v) then
local ret = {};
for i = 0, size(v) - 1 do
ret[] = strsub(v, i, i + 1);
end
return ret;
elseif isMap(v) then
return v;
else
return {v};
end
end
func partition(n, ls)
local ret = {}, a = {};
if !ls then
return ret;
end
if n < 1 then
return ls;
end
for i = 0, size(ls) - 1 do
a[] = ls[i];
if size(a) == n then
ret[] = a;
a = {};
end
end
if size(a) then
ret[] = a;
end
return ret;
end
func partitionBy(fn, ls)
local ret = {}, a = {};
if !ls then
return ret;
end
if !fn then
return ls;
end
local last = null;
for i = 0, size(ls) - 1 do
local t = fn(ls[i]);
if t != last then
if size(a) then
ret[] = a;
a = {};
end
last = t;
end
a[] = ls[i];
end
if size(a) then
ret[] = a;
end
return ret;
end
func isEven(a)
return floor(a / 2) * 2 == a
end
func isOdd(a)
return floor(a / 2) * 2 != a
end
// Testing
// #(reduce (fn [a b] (* a b)) (range 1 (inc %)))
func factorial(n)
return reduce(@{(a, b) return a * b}, range(1, n + 1))
end
// (fn [v l] (reduce (fn [a b] (concat a [v b])) [(first l)] (rest l)))
func interp(v, l)
return reduce(@{(a, b) return concat(a, {v, b})}, {first(l)}, rest(l))
end
func add(a, b)
return a + b;
end
//(fn [& fns]
// (fn [& pars]
// (map (fn [x] (apply x pars)) fns)))
func juxta(fns)
return @{(args) return map(@{(x) return apply(x, args);}, fns)}
end
println("map(@{ (a) return a * 2;}, {1, 2, 3, 4}) -> "
.. map(@{ (a) return a * 2;}, {1, 2, 3, 4}))
println("reduce(@{ (a, b) return a + b;}, 10, {1, 2, 3, 4}) -> "
.. reduce(@{ (a, b) return a + b;}, 10, {1, 2, 3, 4}))
println("flatten({1, {2, 3}, 4, 5}) -> " .. flatten({1, {2, 3}, 4, 5}))
println("range(10) -> " .. range(10))
println(factorial(8))
println('interleave({1, 2, 3, 4}, {"a", "b", "c", "d"}) -> '
.. interleave({1, 2, 3, 4}, {"a", "b", "c", "d"}))
println('hashMap(interleave({"a", "b", "c", "d"}, {1, 2, 3, 4})) -> '
.. hashMap(interleave({"a", "b", "c", "d"}, {1, 2, 3, 4})))
println('distinct(interleave({"a", "b", "c", "d"}, {1, 2, 3, 4})) -> '
.. distinct(interleave({"a", "b", "c", "d"}, {1, 2, 3, 4})))
println("concat({1, 2}, {3, 4}) -> " .. concat({1, 2}, {3, 4}))
println(interp(0, {1, 2, 3}))
println("interpose(0, {1, 2, 3}) -> " .. interpose(0, {1, 2, 3}))
println("juxta({add, min, max}) ({2, 3, 5, 1, 6, 4}) -> "
.. juxta({add, min, max}) ({2, 3, 5, 1, 6, 4}));
println('apply(str, interpose(",", {1, 2, 3, 4})) -> '
.. apply(str, interpose(",", {1, 2, 3, 4})))
println('seq("Hallo") -> ' .. seq("Hallo"));
println('partition(3, interleave({1, 2, 3, 4}, {"a", "b", "c", "d"})) -> '
.. partition(3, interleave({1, 2, 3, 4}, {"a", "b", "c", "d"})))
println('partitionBy(@{(a) return a}, {1,1,1,2,2,3,4,5,5,5,6,5,4,3,3,3}) -> '
.. partitionBy(@{(a) return a}, {1,1,1,2,2,3,4,5,5,5,6,5,4,3,3,3}));
println('distinct({1,1,1,2,2,3,4,5,5,5,6,5,4,3,3,3}) ->'
.. distinct({1,1,1,2,2,3,4,5,5,5,6,5,4,3,3,3}));
println(
map( @{(a) return first(a);},
partitionBy(@{(a) return a}, {1,1,1,2,2,3,4,5,5,5,6,5,4,3,3,3})));
f = @{(a,b) return {take(a, b), drop(a, b)}};
println( f (3, {1, 2, 3, 4, 5, 6}));
println("filter(isEven, {1, 2, 3, 4, 5, 6, 7, 8}) -> " .. filter(isEven, {1, 2, 3, 4, 5, 6, 7, 8}))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment