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