Skip to content

Instantly share code, notes, and snippets.

@Beraliv
Last active January 3, 2018 01:52
Show Gist options
  • Save Beraliv/1e4b04742b2ad09a0398faeeb5e9c0b6 to your computer and use it in GitHub Desktop.
Save Beraliv/1e4b04742b2ad09a0398faeeb5e9c0b6 to your computer and use it in GitHub Desktop.
Douglas Crockford. The Good Parts of JavaScript and the Web. Fun with functions.
const unary = {
identity: x => x,
inc: x => x + 1,
dec: x => x - 1,
double: x => 2 * x,
sqr: x => x * x,
identityf: x => () => unary.identity(x),
};
const binary = {
add: (x, y) => x + y,
sub: (x, y) => x - y,
mul: (x, y) => x * y,
addf: (x, y) => () => binary.add(x, y)
};
const fary = {
lift: binaryf => (x, y) => binaryf(x, y),
curry: f => (...args) => f.length > args.length
? fary.curry(f.bind(null, ...args))
: f(...args),
twice: binaryf => x => binaryf(x, x),
reverse: f => (...args) => f(...args.reverse()),
composeu: (...fs) => base => fs.reduce((v, f) => f(v), base),
composeb: (f, ...fs) => (x, y, ...args) => args.length > 0 && fs.length > 0
? fary.composeb(...fs)(f(x, y), ...args)
: f(x, y),
limit: (f, times) => (...args) => times-- > 0
? f(...args)
: undefined,
memoizedCall: (callf, resf = v => v) => (...args) => resf(callf(...args)),
};
const generator = {
from: index => () => index++,
to: (g, index) => () => fary.memoizedCall(g, v => v < index ? v : undefined)(),
fromTo: (i, j) => generator.to(generator.from(i), j),
element: (arr, g = generator.fromTo(0, arr.length)) => () => fary.memoizedCall(g, v => v !== undefined ? arr[v] : undefined)(),
collect: (g, arr) => () => fary.memoizedCall(g, v => (v !== undefined && arr.push(v), v))(),
filter: (g, f) => () => fary.memoizedCall(g, v => f(v) || v === undefined ? v : generator.filter(g, f)())(),
concat: (g, ...gs) => fary.memoizedCall(g, v => v !== undefined ? v : gs.length > 0 ? generator.concat(...gs)() : undefined),
gensymbf: (symb) => fary.memoizedCall(generator.from(1), v => `${symb}${v}`),
gensymbff: (unaryf, seed) => (symb) => fary.memoizedCall(() => (seed = unaryf(seed), seed), v => `${symb}${v}`),
fibonaccif: (curr, next) => () => fary.memoizedCall((a, b) => (curr = b, next = a + b, curr))(curr, next),
counter: (v) => ({
up: () => ++v,
down: () => --v,
}),
revokable: f => ({
invoke: (...args) => f !== undefined ? f(...args) : undefined,
revoke: () => f = undefined,
}),
};
const monads = {
m: (v, k) => ({
source: k !== undefined ? `${k}` : `${v}`,
value: v
}),
addm: (m1, m2) => ({
source: `(${m1.source}+${m2.source})`,
value: m1.value + m2.value,
}),
liftm: (binaryf, s) => (m1, m2) => ({
source: `(${m1.source}${s}${m2.source})`,
value: binaryf(m1.value, m2.value),
}),
}
const invocations = {
addg: x => {
const more = y => {
if (y !== undefined) {
x += y;
return more;
}
return x;
};
return x !== undefined
? more
: undefined;
},
liftg: f => x => {
const more = y => {
if (y !== undefined) {
x = f(x, y);
return more;
}
return x;
};
return x !== undefined
? more
: undefined;
},
arrayg: x => {
let arr = [];
const more = y => {
if (y !== undefined) {
arr.push(y);
return more;
}
return arr;
};
return x !== undefined
? (arr.push(x), more)
: arr;
},
};
const calc = {
exp: (v) => Array.isArray(v) ? v[0](calc.exp(v[1]), calc.exp(v[2])) : v,
};
// console.log(fary.curry((x, y, z) => x + y - z)(3)(4)(5));
// console.log(fary.curry((x, y, z) => x + y - z)(3)(4, 5));
// console.log(fary.curry((x, y, z) => x + y - z)(3, 4)(5));
// console.log(fary.curry((x, y, z) => x + y - z)(3, 4, 5));
// console.log(fary.curry((x, y, z) => x + y - z)(3, 4, 5, 6));
// console.log(fary.twice(binary.add)(4), fary.twice(binary.mul)(11))
// console.log(fary.reverse(binary.sub)(2, 3))
// console.log(fary.composeu(unary.double, unary.sqr)(5))
// console.log(fary.composeb(binary.add, binary.mul)(2, 3, 5));
const limited_add = fary.limit(binary.add, 1);
// console.log(limited_add(1, 2), limited_add(2, 3));
const fromG = generator.from(0);
// console.log(fromG(), fromG(), fromG());
const fromtoG = generator.to(generator.from(2), 5);
// console.log(fromtoG(), fromtoG(), fromtoG(), fromtoG(), fromtoG())
const fromtoG2 = generator.fromTo(2, 5);
// console.log(fromtoG2(), fromtoG2(), fromtoG2(), fromtoG2(), fromtoG2())
const ele = generator.element(['a', 'b', 'c', 'd', 'e'], generator.fromTo(1, 3));
// console.log(ele(), ele(), ele(), ele());
const ele2 = generator.element(['a', 'b', 'c', 'd', 'e']);
// console.log(ele2(), ele2(), ele2(), ele2(), ele2(), ele2());
const arrForCol = [];
const col = generator.collect(generator.fromTo(2, 5), arrForCol);
// console.log(col(), col(), col(), col(), col(), col(), arrForCol);
const fil = generator.filter(generator.fromTo(0, 15), x => x % 3 === 0);
// console.log(fil(), fil(), fil(), fil(), fil(), fil());
const con = generator.concat(generator.fromTo(0, 2), generator.fromTo(1, 3), generator.fromTo(1, 3));
// console.log(con(), con(), con(), con(), con(), con(), con())
const symbf = generator.gensymbf('G');
// console.log(symbf(), symbf(), symbf(), symbf(), symbf());
const symbf2 = generator.gensymbff(unary.sqr, 2)('F');
// console.log(symbf2(), symbf2(), symbf2(), symbf2(), symbf2());
const fib = generator.fibonaccif(0, 1);
// console.log(fib(), fib(), fib(), fib(), fib(), fib());
const cntr = generator.counter(15);
// console.log(cntr.up(), cntr.down(), cntr.up(), cntr.down())
const rev = generator.revokable(binary.add);
const add_rev = rev.invoke;
// console.log(add_rev(2, 3), rev.revoke(), add_rev(2, 3));
// console.log(JSON.stringify(monads.m(Math.PI, 'pi')), JSON.stringify(monads.m(1)));
// console.log(monads.addm(monads.m(1), monads.m(2)));
// console.log(monads.addm(monads.m(1), monads.m(Math.PI, 'pi')));
// console.log(monads.liftm(binary.add, '+')(monads.m(1), monads.m(Math.PI, 'pi')));
// console.log(calc.exp(4), calc.exp([binary.mul, 6, 1], calc.exp([binary.mul, [binary.add, 2, 3], 1])))
// console.log(invocations.addg(), invocations.addg(2)(), invocations.addg(2)(3)(), invocations.addg(2)(3)(3)())
// console.log(invocations.liftg(binary.add)(), invocations.liftg(binary.add)(2)(), invocations.liftg(binary.add)(2)(3)(), invocations.liftg(binary.add)(2)(3)(3)())
// console.log(invocations.arrayg(), invocations.arrayg(2)(), invocations.arrayg(2)(3)(), invocations.arrayg(2)(3)(3)())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment