function visit(value, key) {
      if (visited[key] === VISIT_DONE) return;
      
      cycle.push(key);
      if (visited[key] === VISIT_IN_PROGRESS) {
        cycle.splice(0, cycle.indexOf(key));
        throw new Error("Cyclic dependency: " + cycle.join(" -> "));
      }
      visited[key] = VISIT_IN_PROGRESS;
      
      if (isString(value)) {
        plan.push(key, [ function() { return $injector.get(value); }], NO_DEPENDENCIES);
      } else {
        var params = $injector.annotate(value);
        forEach(params, function (param) {
          if (param !== key && invocables.hasOwnProperty(param)) visit(invocables[param], param);
        });
        plan.push(key, value, params);
      }
      
      cycle.pop();
      visited[key] = VISIT_DONE;
    }
Studies a set of invocables that are likely to be used multiple times.
     $resolve.study(invocables)(locals, parent, self)
is equivalent to
     $resolve.resolve(invocables, locals, parent, self)
but the former is more efficient (in fact `resolve` just calls `study` internally).
See {@link module:$resolve/resolve} for details.
@function
@param {Object} invocables
@return {Function}