Created
January 4, 2012 21:53
-
-
Save rjeschke/1562374 to your computer and use it in GitHub Desktop.
Weel functional programming library (clojure-like)
This file contains 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
/* | |
* 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