Skip to content

Instantly share code, notes, and snippets.

@indongyoo
Last active February 16, 2018 13:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save indongyoo/4f7914e120aeb600a84face376526fba to your computer and use it in GitHub Desktop.
Save indongyoo/4f7914e120aeb600a84face376526fba to your computer and use it in GitHub Desktop.
function then(f, a) {
return arguments.length == 1 ?
a => then(f, a) :
a instanceof Promise ? a.then(f) : f(a);
}
function toIterator(data) {
if (data == null) data = [];
if (!data[Symbol.iterator]) data = Object.values(data);
return data[typeof data.values == 'function' ? 'values' : Symbol.iterator]();
}
function reduceIter(f, acc, iter) {
return then(function recur(acc) {
for (const val of iter)
if ((acc = f(acc, val)) instanceof Promise)
return acc.then(recur);
return acc;
}, acc);
}
function curry2(f) {
return function(a) {
return arguments.length > 1 ? f(...arguments) : function() { return f(a, ...arguments); }
}
}
const reduce = curry2(function(f, data) {
const iter = toIterator(data);
return reduceIter(f, iter.next().value, iter)
});
const reduceAcc = curry2(function(f, acc, data) {
return arguments.length == 2 ?
data => reduceAcc(f, clone(acc), data) :
reduceIter(f, acc, toIterator(data));
});
function clone(data) {
if (data == null || typeof data != 'object') return data;
return Array.isArray(data) ? [...data] : Object.assign({}, data);
}
function call(f, arg) {
return callRight(arg, f);
}
function callRight(arg, f) {
return arg instanceof Tuple ? f(...arg) : arg === undefined ? f() : f(arg);
}
function go() {
return reduce(callRight, arguments);
}
function pipe(...fs) {
return function() {
return reduceAcc(callRight, toTuple(arguments), fs);
};
}
class Tuple {
constructor() {
this.value = arguments;
}
[Symbol.iterator]() {
return this.value[Symbol.iterator]();
}
}
function tuple(...args) {
if (args.length == 1) return args[0];
return find(arg => arg instanceof Promise, args) ?
then(toTuple, Promise.all(args)) :
new Tuple(...args);
}
function toTuple(list) {
return list.length == 1 ? list[0] : new Tuple(...list);
}
function find(f, data) {
if (arguments.length == 1) return data => find(f, data);
const iter = toIterator(data);
return function recur(bool) {
for (const val of iter)
if (bool = f(val))
return then(b => b ? val : recur(), bool);
} ();
}
const isUndefined = val => val === undefined;
const not = bool => !bool;
const negate = f => pipe(f, not);
const _none = pipe(find, isUndefined),
none = curry2(_none);
const some = curry2(negate(_none));
const every = curry2(pipe((f, data) => find(negate(f), data), isUndefined));
const append = curry2(function(list, item) {
return list.push(item), list;
});
const map = curry2(function(f, data) {
return reduceAcc((list, val) => go(val, f, append(list)), [], data);
});
const cmap = curry2(function(f, data) {
return Promise.all(reduceAcc((list, val) => append(list, f(val)), [], data));
});
const each = curry2(function(f, data) {
return reduceAcc((nil, val) => f(val), null, data);
});
function unless(...fs) {
var f = cond(...fs)(tuple);
return function(...fs) {
return f.else(...fs);
};
}
function cond() {
var pbs = [];
function predicate(f) {
pbs.push({
predicate: typeof f == 'function' ? pipe(...arguments) : b => b == f
});
return body;
}
function body() {
pbs[pbs.length-1].body = pipe(...arguments);
return predicate;
}
predicate.else = function() {
predicate(() => true) (...arguments);
return evaluator;
};
var evaluator = pipe(function() {
return go(pbs,
find(pb => pb.predicate(...arguments)),
pb => pb.body(...arguments));
});
return predicate(...arguments);
}
function tap(f) {
return function() {
return go(f(...arguments), _=> toTuple(arguments));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment