node package manager
Painless code sharing. npm Orgs help your team discover, share, and reuse code. Create a free org »

dispatcher

dispatcher

Pattern matching for JavaScript.

Library can be used to implement functions supporting range of different dispatchers, in a declarative manner avoiding mess of conditional blocks & manual argument validations. While primarily this aims to improve code readability and maintainability, in some cases this can be useful to optimize specific, hot code paths.

Examples

 
var dispatcher = require('dispatcher/core').dispatcher
 
function number(value) {
  if (typeof(value) !== 'number') throw Error('Not a number')
  return value
}
 
var sum = dispatcher({ doc: "sums given numbers", added: "0.1.0" },
  // If no arguments are passed then 0. 
  [], function() { return 0 },
  // If only one argument is passed return back. 
  [ number ], function(x) { return x },
  // Optimize two argument case. 
  [ number, number ], function(x, y) { return x + y },
  // If more then two then take all the args starting from second as 
  // rest array. 
  [ number, [] ], function (x, rest) {
    called.number_rest ++;
    return rest.reduce(function(x, y) {
      return x + y
    }, x)
  })
 
 
sum()               // => 0 
sum(1)              // => 1 
sum(2, 3)           // => 5 
sum(2, 5, 17, 1)    // => 25 
sum([ 4 ])          // TypeError -> Unsupported dispatcher 
 
 
// Define guards 
function string(value) {
  if (typeof(value) !== 'string') throw Error('Not a string')
  return value
}
function lambda(value) {
  if (typeof(value) !== 'function') throw Error('Not a function')
  return value
}
function array(value) {
  if (!Array.isArray(value)) throw Error('Not an array')
  return value
}
function object(value) {
  if (!value || typeof(value) !== 'object') throw new Error('Not an object')
  return value
}
 
var map = dispatcher(
  // Function that operates on strings 
  [ lambda, string ], function(lambda, string) {
    var index = -1, length = string.length, chars = []
    while (++index < length) chars[index] = lambda(string[index])
    return chars.join('')
  },
  // Function that operates on arrays 
  [ lambda, array ], function(lambda, array) {
    var index = -1, length = array.length, elements = []
    while (++index < length) elements[index] = lambda(array[index])
    return elements
  },
  // Function that operates on objects 
  [ lambda, object ], function(lambda, object) {
    var pair, value = Object.create(Object.getPrototypeOf(object))
    for (var key in object) {
      pair = lambda(key, object[key])
      value[pair[0]] = pair[1]
    }
    return value
  },
  // Function that operates on everything else 
  [ lambda, , ], function(lambda, value) {
    return lambda(value)
  })
 
 
map(function($) { return $.toUpperCase() }, 'hello world')
// => 'HELLO WORLD' 
 
map(function($) { return $ * 2 }, [ 1, 2, 3 ])
// => [ 2, 4, 6 ] 
 
map(function(k, v) { return [ '@' + k, v + '!' ] }, { foo: 1, bar: 'baz' })
// => { '@foo': '1!', '@bar': 'baz!' } 
 
map(function($) { return $ + 1 }, 6)
// => 7 
 
map(function($) { return $ + '!' }, 'hello', 'world')
// TypeError -> Unsupported dispatcher 

Install

npm install dispatcher