 
       storedValues
 
+  _cachedValueFunction: (name, calcFunction) ->
+    runner = this
+    ops = new Operations name
+    ->
+      if runner.slots[name] is Invalid
+        runner.slots[name] = try
+            ops._valueCheck calcFunction.apply runner.sheet, []
+          catch e
+            ops._error e
+
+      runner.slots[name]
 
   _userFunctionSubject: (name) -> @userFunctionSubjects[name]
   _unknownUserFunctionSubject: (name) -> (@userFunctionSubjects[name] = @_newUserFunctionSubject(name, new CalculationError(name, "Unknown name: " + name)))

  @STREAM_RETURN = 'streamReturn'
  @AGGREGATE_RETURN = 'aggregateReturn'

  isRxObservable = (func) -> typeof func.subscribe == 'function'
  returnsStream = (func) -> func.kind == SheetRunner.STREAM or func.kind == SheetRunner.TRANSFORM_STREAM or func.returnKind == SheetRunner.STREAM_RETURN or func.returnKind == SheetRunner.SEQUENCE_RETURN
  returnsAggregate = (func) -> func.returnKind == SheetRunner.AGGREGATE_RETURN

      @valueChanges.onNext [name, value]
    subj

  _invalidateDependents: (name) -> @slots[n] = Invalid for n in @_functionsUsing name

  _functionsUsing: (name) -> (n for n, f of @userFunctions when _.includes @functionsUsedBy(n), name)

  _recalculate: ->
    for name, subj of @userFunctionSubjects
      subj.onNext @_sheetValue name

  _sheetValue: (name) -> @sheet[name].apply @sheet, []

  _allFunction: (name) ->
    runner = this
