function stack (arrays, axis) {
  axis = axis || 0;
  if (!arrays || arrays.length === 0) {
    throw new errors.ValueError('need at least one array to stack');
  }
  arrays = arrays.map(function (a) { return _.isNumber(a) ? a : NdArray.new(a); });
  var expectedShape = arrays[0].shape || []; // for numbers

  for (var i=1; i<arrays.length; i++){
    var shape = arrays[i].shape || []; // for numbers
    var len = Math.max(expectedShape.length, shape.length);
    for (var j = 0; j < len; j++){
      if (expectedShape[j] !== shape[j]) throw new errors.ValueError('all input arrays must have the same shape');
    }
  }
  var stacked;
  if (expectedShape.length === 0) { // stacking numbers
    stacked = concatenate(arrays);
  } else {
    stacked = zeros([arrays.length].concat(expectedShape));
    for (var i=0; i<arrays.length; i++) {
      stacked.pick(i).assign(arrays[i], false);
    }
  }

  if (axis) {
    // recompute neg axis
    if (axis < 0) axis = stacked.ndim + axis;

    var d = stacked.ndim;
    var axes = new Array(d);
    for (var i = 0; i < d; i++){
      axes[i] = i < axis ? i + 1 : i === axis ? 0 : i;
    }

    return stacked.transpose(axes);
  }
  return stacked;
}
Join a sequence of arrays along a new axis.
The axis parameter specifies the index of the new axis in the dimensions of the result.
For example, if axis=0 it will be the first dimension and if axis=-1 it will be the last dimension.
@param {Array} sequence of array_like
@param {number} [axis=0] The axis in the result array along which the input arrays are stacked.
@return {Array} The stacked array has one more dimension than the input arrays.