Skip to content

Instantly share code, notes, and snippets.

@remydagostino
Last active August 29, 2015 14:05
Show Gist options
  • Save remydagostino/3919a92a538d5ffe8557 to your computer and use it in GitHub Desktop.
Save remydagostino/3919a92a538d5ffe8557 to your computer and use it in GitHub Desktop.
Curried Functions With Guards
/*
Do you think this might be a useful way to do functional programming
in Javascript?
Gaurded, curried functions are created like:
Lambda(2).case(predicate, expression).case(predicate2, expression2);
The `2` specifies that the function accepts two arguments, it will
be partially applied if it is called with fewer (just like autocurry)
Each case statement has a function which checks the inputs, if it
returns `true` then the expression will be called with the function
arguments. Only the first matching predicate is executed.
It would probably be better if the Lambda functions were immutable...
*/
// Turns arguments into array
var argsToArray = function(args) {
return Array.prototype.slice.call(args);
};
// Creates an auto-curried pattern matching function
// that can be extended with .case(predicate, expression)
var Lambda = function(numArgs) {
var guard, fn, tests;
tests = [];
fn = function() {
var i, test, result;
for (i = 0; i < tests.length; i++) {
test = tests[i];
if (test.predicate.apply(this, arguments) === true) {
return test.expression.apply(this, arguments);
}
}
throw new Error('No matching case found for: ' + argsToArray(arguments));
};
guard = function() {
var args = arguments;
if (args.length < numArgs) {
return function innerGuard() {
var allArgs = argsToArray(args).concat(argsToArray(arguments));
return guard.apply(this, allArgs);
};
}
else {
// Call the function
return fn.apply(this, args);
}
};
guard.case = function(predicate, expression) {
tests.push({ predicate: predicate, expression: expression });
return guard;
};
return guard;
};
// Functor Map
var fmap = Lambda(2).case(
function(fn, a) {
return typeof fn == 'function' && Array.isArray(a);
},
function(fn, a) { return a.map(fn); }
);
// Addition
var plus = Lambda(2).case(
function(a, b) {
return typeof a == 'number' && typeof b == 'number';
},
function(a, b) {
return a + b;
}
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment