// ---------- a selection of library functions -----------------------------
const curry = f => (...args) =>
args.length >= f.length
? f(...args)
: curry(f.bind(undefined, ...args))
const compose = (...fns) => xs => fns.reduceRight((v, f) => f(v), xs)
const filter = curry((f, xs) => Array.prototype.filter.call(xs, f))
const every = curry((f, xs) => Array.prototype.every.call(xs, f))
const map = curry((f, xs) => Array.prototype.map.call(xs, f))
const gt = curry((targ, n) => n > targ)
const lt = curry((targ, n) => n < targ)
const isEven = n => n % 2 === 0
const allTrue = curry((preds, x) => every(pred => pred(x), preds))
const double = n => n * 2
// ---------- end library functions ---------------------------------------
// Application code...
const doubleEvensBetween5And15 = compose(
map(double),
// below, how to log to the console within a compose call.
ary => console.log('Intermediate array ', ary) || ary, // => [6, 8, 10, 12, 14]
filter(allTrue([isEven, lt(15), gt(5)]))
)
const integers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
console.log(doubleEvensBetween5And15(integers))
// => [12, 16, 20, 24, 28]