Skip to content

Instantly share code, notes, and snippets.

@laser
Last active August 29, 2015 14:23
Show Gist options
  • Save laser/74dac8642ab1c376f4ef to your computer and use it in GitHub Desktop.
Save laser/74dac8642ab1c376f4ef to your computer and use it in GitHub Desktop.
composing non-unary functions
var async = require('async');
var _ = require('lodash');
var $ = require('./utilities.js');
//////////////////////////////////////////////////
// two simple unary functions, for demonstration
// purposes
function dubble(x) {
return x * 2;
}
function addThree(x) {
return x + 3;
}
// the good stuff below!
//////////////////////////////////////////////////
// original fn - must introduce an anonymous
// expression to work around the fact that we want
// to use the expression `n` twice
//
var lameFn = function(n, callback) {
async.compose(
$.callbackify(_.last),
$.callbackify(_.partial($.report, n)),
$.callbackify($.addThree),
$.callbackify($.dubble)
)(n, callback);
}
lameFn(10, function(err, output) {
assert('Should replicate values to two slots', output === 23);
});
//////////////////////////////////////////////////
// new - created through composition!
//
var coolFn = async.compose(
$.callbackify(_.last), // return the right side
$.callbackify(report), // a binary function: outputs left and right sides
_.partial($.secondA, $.callbackify(addThree)), // apply to the right side
_.partial($.secondA, $.callbackify(dubble)), // apply to the right side
$.callbackify(_.partial($.replicate, 2)) // create an array with left and right sides holding same value
);
coolFn(10, function(err, output) {
assert('Should replicate values to two slots', output === 23);
});
var async = require('async');
var _ = require('lodash');
//////////////////////////////////////////////////
// for applying two functions (in parallel) over a
// two-element array (as close to a bifunctor) as
// we're gonna get in this language
function bimapA(f1, f2, xs, callback) {
async.parallel([
_.partial(f1, xs[0]),
_.partial(f2, xs[1])
], callback);
}
var firstA = _.partial(bimapA, _, callbackify(_.identity));
var secondA = _.partial(bimapA, callbackify(_.identity));
//////////////////////////////////////////////////
// transmute a direct-style function to a CPS
// function
function callbackify (f) {
return function callbackifyInner () {
var args = _.toArray(arguments);
var argsWithoutLast = _.take(args, args.length - 1);
var callback = _.last(args);args[args.length - 1];
var result, error;
try {
result = f.apply(this, argsWithoutLast);
}
catch (e) {
error = e;
}
callback(error, result);
}
}
function report(xs) {
console.log('left: ' + xs[0], 'right: ', xs[1]);
return xs;
}
function assert(msg, expr) {
if (!expr) throw msg;
console.log('Assertion: ' + msg + ' held true.');
return true;
}
function replicate(n, x) {
var xs = [];
while (n--) {
xs.push(x);
}
return xs;
}
module.exports = {
callbackify: callbackify,
assert: assert,
report: report,
replicate: replicate,
callbackify: callbackify,
bimapA: bimapA,
firstA: firstA,
secondA: secondA
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment