FuncTools is a small library of functional programming tools for MooTools.
Sometimes you want to define a single function that dispatches on arity, for example say you want to sum a range of numbers. You could loop over the array with an accumulator, but it’s much more fun to use Function.reduce.
var sum = Function.dispatch(
function(a) { return a; },
function(a, b) { return a + b.first(); }
);
sum.reduce($range(100));
It’s very useful to have an implementation of partial for currying arguments to a function in order, Function.partial helps here:
var partialFn = function(a, b) { return a * b }.partial(null, 3);
partialFn(4); // 12
However you don’t always have control of the argument order- i.e. using someone else’s library. If for some reason you need to supply arguments out of order you should use Function.curry:
var _ = Function._;
function abc(a, b, c) { return a + b + c; };
var curried = abc.curry(null, _, _, 3);
curried = curried(1);
curried(_, 2); // 6
Being able to compose functions is also very useful:
var MyClass = new Class({
initialize: function(name) { this.name = name; },
sayHello: function() {
console.log("Hello from " + this.name)
}
});
var ctorfn = function(name) { return new MyClass(name); };
["John", "Mary", "Bob"].map(Function.comp(ctorfn, Function.msg("sayHello")));
Function decoration is also a very powerful technique. The Promises library uses this to great effect. We can memoize results for example. You would not want to run the following calculation without memoization:
var fib = function (n) {
return n < 2 ? n : fib(n-1) + fib(n-2);
}.decorate(Function.memoize);
fib(100);
JavaScript is a fairly loose language – sometimes you just want to add a little bit of sanity. The Function.pre decorator can help here. You can specify the validating function for each argument:
var isEven = function(n) { return n % 2 == 0; };
var isOdd = $not(isEven);
var add = function(a, b) { return a + b; }.decorate(Function.pre([isEven, isOdd], true));
add(2, 3); // 5
add(2, 2); // throws exception
An example of a postcondition using Function.post:
var isSmith = Function.comp(Function.acc('last'), Function.eq('Smith'));
var fn = function(first, last) {
return {first:first, last:last};
}.decorate(Function.post(isSmith, true));
fn("Bob", "Smith");
fn("Bob", "Howard"); // throws exception
Often it’s very nice if you can treat an Array or a Hash as a function:
var address = {
"city": "New York",
"state": "New York",
"zip": 100018,
"street": "350 5th Avenue",
"building": "Empire State",
"floor": 32
};
["building", "street", "city"].map($H(address).asFn()); // ["Empire State", "350 5th Avenue", "New York"]
var ary = ['cat', 'dog', 'bird', 'zebra', 'lion'];
[1, 3, 2].map(ary.asFn()); // ['dog', 'zebra', 'bird']
- $identity
- $callable
- $range
- $isnull
- $notnull
- $repeat
- $get
- Function.not
- Function.eq
- Function.iterate
- Function.decorate
- Function.comp
- Function.partial
- Function.curry
- Function.memoize
- Function.pre
- Function.arglist
- Function.dispatch
- Function.reduce
- Function.acc
- Function.msg
- Array.first
- Array.rest
- Array.drop
- Array.tail
- Array.head
- Array.partition
- Array.asFn
- Hash.asFn
- Hash.extract