text: import map from "./map";
  
  export default function() {
    var keys = [],
        sortKeys = [],
        sortValues,
        rollup,
        nest;
  
    function apply(array, depth, createResult, setResult) {
      if (depth >= keys.length) return rollup
          ? rollup(array) : (sortValues
          ? array.sort(sortValues)
          : array);
  
      var i = -1,
          n = array.length,
          key = keys[depth++],
          keyValue,
          value,
          valuesByKey = map(),
          values,
          result = createResult();
  
      while (++i < n) {
        if (values = valuesByKey.get(keyValue = key(value = array[i]) + "")) {
          values.push(value);
        } else {
          valuesByKey.set(keyValue, [value]);
        }
      }
  
      valuesByKey.each(function(values, key) {
        setResult(result, key, apply(values, depth, createResult, setResult));
      });
  
      return result;
    }
  
    function entries(map, depth) {
      if (depth >= keys.length) return map;
  
      var array = [],
          sortKey = sortKeys[depth++];
  
      map.each(function(value, key) {
        array.push({key: key, values: entries(value, depth)});
      });
  
      return sortKey
          ? array.sort(function(a, b) { return sortKey(a.key, b.key); })
          : array;
    }
  
    return nest = {
      object: function(array) { return apply(array, 0, createObject, setObject); },
      map: function(array) { return apply(array, 0, createMap, setMap); },
      entries: function(array) { return entries(apply(array, 0, createMap, setMap), 0); },
      key: function(d) { keys.push(d); return nest; },
      sortKeys: function(order) { sortKeys[keys.length - 1] = order; return nest; },
      sortValues: function(order) { sortValues = order; return nest; },
      rollup: function(f) { rollup = f; return nest; }
    };
  }
  
  function createObject() {
    return {};
  }
  
  function setObject(object, key, value) {
    object[key] = value;
  }
  
  function createMap() {
    return map();
  }
  
  function setMap(map, key, value) {
    map.set(key, value);
  }
  