Skip to content

Instantly share code, notes, and snippets.

@BretCameron
Created October 15, 2019 20:46
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save BretCameron/0086bff21d5019824115aa2818ccbf69 to your computer and use it in GitHub Desktop.
Save BretCameron/0086bff21d5019824115aa2818ccbf69 to your computer and use it in GitHub Desktop.
An example container used for functional programming, to help separate impure functions from pure logic.
const isFunction = fn => fn && Object.prototype.toString.call(fn) === '[object Function]';
const isAsync = fn => fn && Object.prototype.toString.call(fn) === '[object AsyncFunction]';
const isPromise = p => p && Object.prototype.toString.call(p) === '[object Promise]';
const tap = f => x => {
f(x);
return x;
};
class Container {
constructor(fn) {
this.value = fn;
if (!isFunction(fn) && !isAsync(fn)) {
throw new TypeError(`Container expects a function, not a ${typeof fn}.`);
};
}
map(fn) {
if (!isFunction(fn) && !isAsync(fn)) {
throw new TypeError(`The map method expects a function, not a ${typeof fn}.`);
};
return new Container(
() => isPromise(this.value()) ?
this.value().then(fn) : fn(this.value())
)
}
run() {
return this.value();
}
};
const sayHello = () => 'Hello';
const addName = (name, str) => str + ' ' + name;
const container = new Container(sayHello);
const greet = container
.map(addName.bind(this, 'Joe Bloggs'))
.map(tap(console.log));
greet.run();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment