Last active
January 3, 2018 01:52
-
-
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.
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
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