code: function batcher(state, tasks, callback)
  {
    // `state` is optional
    // if first arguments is Array
    // consider it as list of jobs
    if (Array.isArray(state))
    {
      callback = tasks;
      tasks    = state;
      state    = {};
    }
  
    // make sure state is an object
    if (typeOf(state) != 'object')
    {
      throw new TypeError('Initial state should be an object');
    }
  
    // decouple things
    state = mixin(state, stateMethods);
    tasks = tasks.slice();
  
    // add hidden current task reference
    Object.defineProperty(state, '_currentTask', {
      enumerable: false,
      writable: true
    });
  
    report('init', clone(state));
  
    // process tasks one by one
    // use provided callback or default to the reporting
    iterator(state, tasks, function(error, finalState)
    {
      // if no final state provided use original reference
      finalState = finalState || state;
  
      if (error)
      {
        // set exitCode to error value
        // don't anticipate error with code 0
        process.exitCode = error.code || 1;
      }
  
      // pass it to the reporter or callback
      return callback ? callback(error, finalState) : report('done', finalState, error);
    });
  }
docs: --- Public functions 
  Initiates batch processing of the provided tasks
  
  @param   {object} [state] - initial state
  @param   {array} tasks - list of tasks to process
  @param   {function} callback - invoked after all the tasks have been processed
  @returns {void}