f.g.h(x) === f(g(h(x)))const add1 = x => x + 1;
const double = x => x * 2;
const square = x => x ** 2;
const _ = makeComposable({ add1, double, square });
console.assert(
_.double.add1(1) === double(add1(1))
);
console.assert(
_.double.add1.add1.square(100) === double(add1(add1(square(100))))
);
console.assert(
_.add1.square.add1.double(3) === add1(square(add1(double(3))))
);- Trap property lookups, and redirect all method lookups to a
Mapof the instrumented functions. This enables chained lookup, e.g.double.square.add1. - Trap function applications, and pass the result to another pre-bound function. This enables function composition, e.g.
double.square(5)is reallydouble(square(5)).
Notational abuse is confusing and this should probably never be used in practice. Additionally, here are some other glaring problems with this implementation:
- Only works with unary functions (i.e. functions of a single argument) right now
- Does absolutely nothing to handle naming collisions with the prototype chain (e.g.
apply) - One zillion other edge cases I haven't thought about