athena

Strategically gives you awesome functional combinators for an abstraction war!

Athena

Athena is a library that provides core functional combinators like Curry, Compose, Partial, etc. Combinators range from lambda calculus, to general higher-order functions, to logic and control-flow combinators.

var _ = require('athena')
 
function add2(ab) { return a + b }
 
var add = _.curry(add2)
 
_.compose( _.add(1)
         , _.uncurry(add2)
         , _.k([2, 3])
         )()
// => 6 

The easiest way is to grab it from NPM (use browserify if you're on a Browser):

$ npm install athena

If you really want to continue suffering with old and terrible module systems (or use no module system at all), you can run make dist yourself:

$ git clone git://github.com/killdream/athena
$ cd athena
$ npm install
$ make dist
# Then use `dist/athena.umd.js` wherever you want.

This library assumes an ES5 environment, but can be easily supported in ES3 platforms by the use of shims. Just include es5-shim :3

$ npm test

Does nothing.

noop: () -> ()
noop(1) // =>  

The constant function in lambda calculus.

k: A -> () -> A
k(1)(2) // => 1 

The identity function in lambda calculus.

id: A -> A
id(1) // => 1 

Executes the given function after (at least) the given seconds.

delay: number -> (A... -> B) -> timer-id
delay(0.5, function(){ console.log(2) })
console.log(1)
// 1 
// 2 

Executes the function asynchronously, as soon as possible.

defer: (A... -> B) -> ()
defer(function(){ console.log(2) })
console.log(1)
// 1 
// 2 

Function composition (compose(f, g)(x) = f(g(x))).

compose: (A... -> B)... -> A... -> B
function double(x){ return x + x }
function squared(x){ return x * x }
 
var doubleSquared = compose(squared, double)
doubleSquared(2) // => 16 

Creates a curried function from an uncurried one.

curry: number?, (A... -> B), [A]? -> A... -> (A... -> B) | B
function add(ab){ return a + b }
var curriedAdd = curry(add)
 
var add1 = curriedAdd(1)
add1(2) // => 3 

Partially applies the given arguments to a function.

partial: (A... -> B), A... -> A... -> B
function add(ab){ return a + b }
var add1 = partial(add, 1)
add1(2) // => 3 

Transforms a curried function to a function on lists.

uncurry: (A... -> B) -> [A] -> B
var toArray = Function.call.bind([].slice)
function add(ab){ return a + b }
function sum(){ return toArray(arguments).reduce(add, 0) }
 
sum([1, 2, 3]) // => 6 

Transforms a curried function to a function on lists, where the first item of the list is the value of this.

uncurryBind: (A... -> B) -> [this, A...] -> B
var bag = {
  items: [],
  addfunction() {
    this.items.push.apply(this.items, arguments)
  }
}
 
var addToBag = uncurryBind(bag.add)
var otherBag = { __proto__: bag, items: [] }
 
addToBag([otherBag, 1, 2])
 
otherBag.items // => [1, 2] 

Wraps the invocation of f in the given advice. The advice can then decide what to do with the function.

f: (A... -> B)
wrap: (f, C... -> D) -> f -> C... -> D
function add(ab) { return a + b }
function trace(fab) {
  console.log('Calling %s with: %s, %s', f.name, a, b)
  var result = f(a, b)
  console.log('Returned: %s', result)
  return result
}
 
var tracedAdd = wrap(trace, add)
 
tracedAdd(1, 2)
// Calling add with: 1, 2 
// Returned: 3 
// => 3 

either(p, f, g)(a) is the same as p(a)? f(a) : g(a).

either: (A... -> bool) -> (A... -> B) -> (A... -> C) -> A... -> B | C
function isNegative(a) { return a < 0 }
function negate(a) { return -}
var abs = either(isNegative, negate, id)
 
abs(-2) // => 2 
abs(2) // => 2 

unless(p, f)(a) is the same as if (!p(a)) f(a).

This is also aliased as _unless for LiveScript/CoffeeScript.

unless: (A... -> bool) -> (A... -> B) -> A... -> maybe B
function isCallable(a){ return typeof a == 'function' }
function raise(e){ throw new Error(e) }
function unwrap(f){ return f() }
 
unless(isCallable, unwrap)(function(){ return 1 }) // => 1 

Yields a function that will apply f the first N times.

limit: number -> (A... -> B) -> (A... -> maybe B)
var f = limit(2, id)
[f(1), f(2), f(3)] // => [1, 2, undefined] 

Yields a function that will apply f only once.

once: (A... -> B) -> (A... -> maybe B)
var f = once(id)
[f(1), f(2)] // => [1, undefined] 

Yields a function that will only apply f before the predicate holds.

This is also aliased as _until for LiveScript/CoffeeScript.

until: (A... -> bool) -> (A... -> B) -> (A... -> maybe B)
function greaterThan(ab){ return a > b }
function sub(ab){ return a - b }
 
var subGreater = until(greaterThan, sub)
 
subGreater(1, 2) //=>  
subGreater(2, 2) //=>  
subGreater(3, 2) //=> 1 
subGreater(0, 2) //=> -2 

Yields a function that will only apply f after the predicate holds.

This is also aliased as _when for LiveScript/CoffeeScript.

when: (A... -> bool) -> (A... -> B) -> (A... -> maybe B)
function greaterThan(ab){ return a > b }
function sub(ab){ return a - b }
 
var subGreater = when(greaterThan, sub)
 
subGreater(1, 2) //=> -1 
subGreater(2, 2) //=> 0 
subGreater(3, 2) //=>  
subGreater(0, 2) //=>  

Yields a function that will apply each function in turn, and return the value of the first truthy one.

This is also aliased as _or for LiveScript/CoffeeScript.

or: (A... -> B)... -> A... -> maybe B

Yields a function that will apply each function in turn, and return the value of the last truthy one.

This is aliased as _and for LiveScript/CoffeeScript.

and: (A... -> B)... -> A... -> maybe B

Yields a function that will return the negated result of applying f.

not: (A... -> bool) -> A... -> bool

MIT/X11. ie.: do whatever you want.