Skip to content

Instantly share code, notes, and snippets.

@remydagostino
Last active August 29, 2015 14:04
Show Gist options
  • Save remydagostino/f03113c6852bfaa1ad31 to your computer and use it in GitHub Desktop.
Save remydagostino/f03113c6852bfaa1ad31 to your computer and use it in GitHub Desktop.
/* Functional Programming makes you look like a mad man
* Exhibit A.
* I define 23 helper functions so that I can write my solution point-free style
* - Remy D'Agostino
*/
// :: a -> b -> bool
var eq = autocurry(function(a, b) { return a === b; });
// :: a -> b -> bool
var and = autocurry(function(a, b) { return a && b; });
// :: a -> a
var id = function(a) { return a; };
// :: num -> num -> bool
var gte = autocurry(function(a, b) { return b >= a; });
// :: num -> num -> num
var add = autocurry(function(a, b) { return a + b; });
// :: num -> num -> num
var subtract = autocurry(function(a, b) { return a - b; });
// :: num -> num -> num
var modulo = autocurry(function(a, b) { return b % a; });
// :: a -> (-> a)
var constant = id.bind.bind(null, null);
// :: string -> object -> a
var dot = autocurry(function(k, v) { return v[k]; });
// :: object -> string -> a
var lookup = autocurry(function(v, k) { return v[k]; });
// :: (a -> b -> a) -> a -> [b] -> [a]
var reduce = autocurry(function(f, v, a) {
return a.reduce(function(m, x) { return f(m,x); }, v);
});
// :: (a -> b) -> [a] -> [b]
var map = autocurry(function(f, a) { return a.map(function(v) { return f(v); }); });
// :: [a] -> int
var arrLength = dot('length');
// :: [a] -> int
var max = function(arr) { return reduce(Math.max, 0, arr); };
// :: (a -> bool) -> [a] -> bool
var every = autocurry(function(f, a) {
return reduce(function(m, v) { return m && f(v); }, true, a);
});
// :: (b -> c) -> (a -> b) -> (a -> c)
var compose = autocurry(function(f1, f2) {
return function(v) {
return f1(f2(v));
};
});
// :: a -> int -> [a] -> [a]
var padLeft = autocurry(function(item, length, arr) {
return arrayRepeat(item, length - arr.length).concat(arr);
});
// :: a -> [a] -> [a]
var trimLeft = autocurry(function(item, arr) {
if (arr[0] !== item) {
return arr;
}
return trimLeft(item, arr.slice(1));
});
// :: a -> int -> [a]
var arrayRepeat = autocurry(function(item, length) {
if (length <= 0) { return []; }
return [item].concat(arrayRepeat(item, length - 1));
});
// :: [a] -> [a] -> (a -> a -> b) -> [b]
var zipWith = autocurry(function(fn, first, second) {
return first.reduce(function(memo, v, i) {
return memo.concat(fn(v, second[i]));
}, []);
});
// :: num -> num -> num -> {num, num}
var sumWithCarry = autocurry(function(base, a, b) {
return {
sum : (a + b) % base,
carry: (a + b) >= base ? 1 : 0
};
});
/// CURRY
function curry(fn) {
var args = Array.prototype.slice.call(arguments, 1);
return function () {
return fn.apply(fn, args.concat(Array.prototype.slice.call(arguments)));
};
}
function autocurry(fn, numArgs) {
var expectedArgs = numArgs || fn.length;
return function () {
if (arguments.length < expectedArgs) {
// A curried version of fn
var curried = curry.apply(this, [fn].concat(Array.prototype.slice.call(arguments)));
var rem = numArgs - arguments.length;
// If we still don't have the expected number of arguments then return
return expectedArgs - arguments.length > 0 ? autocurry(curried, rem) : curried;
}
else {
return fn.apply(this, arguments);
}
};
}
/**
* Add Array Numbers
*
* 654 + 59 = 713
* addArrayNumbers([6, 5, 4], [5, 9]) // [7, 1, 3];
*
* @param {Array} first
* @param {Array} second
* @return {Array}
*/
function addArrayNumbers(first, second) {
var pair, padded, zipped, carry, result;
if (every(eq(0), second)) {
return first;
}
pair = map(trimLeft(0), [first, second]);
padded = map(padLeft(0, max(map(arrLength, pair))), pair);
zipped = zipWith(sumWithCarry(10), padded[0], padded[1]);
result = map(dot('sum'), zipped);
carry = map(dot('carry'), zipped).concat([0]);
return addArrayNumbers(result, carry);
};
if (module && module.exports) {
module.exports = addArrayNumbers;
}
else {
window.addArrayNumbers = addArrayNumbers;
}
console.info(addArrayNumbers([6, 5, 4], [5, 9]));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment