> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dairy.foundation/llms.txt
> Use this file to discover all available pages before exploring further.

# LateInitCell and Derivatives

LateInitCell starts with null inside, but insists that it doesn't contain a null
value! It will throw an exception if you try to get the contents and they are
null.

The next cells are all built off the LateInitCell back, so they all share the
following additional utility methods:

<CodeGroup>
  ```java Java theme={null}
  LateInitCell<Distance> late = new LateInitCell<>();
  // attempting to get the data out now would throw an error
  late.accept(Distances.mm(10));
  late.getInitialised(); // true
  // late.accept(null); this doesn't work
  late.invalidate(); // now the cell is back to containing null
  late.getInitialised(); // false
  late.safeGet(); // will not throw an error if the contents are null
  late.safeInvoke(ref -> { // only runs if the contents aren't null
     return ref.plus(Distances.mm(12));
  }); // null
  ```

  ```kt Kotlin theme={null}
  val late = LateInitCell<Distance>()
  // attempting to get the data out now would throw an error
  late.accept(10.mm)
  late.initialised // true
  // late.accept(null) this doesn't work
  late.invalidate() // now the cell is back to containing null
  late.initialised // false
  late.safeGet() // will not throw an error if the contents are null
  late.safeInvoke { // only runs if the contents aren't null
      it + 12.mm
  } // null
  ```
</CodeGroup>

# LazyCell

LazyCell will lazily evaluate its contents from a function whenever you attempt
to obtain the contents and they are null.

Combine this with `invalidate()` in order to re-evaluate the contents using the
function.

Several modules have their own wrapper of this, e.g. Core has the
`OpModeLazyCell` and `OpModeFreshLazyCell` and Mercurial has the
`SubsytemObjectCell`. These wrappers provide additional functionality tied to
their specific domains.

<CodeGroup>
  ```java Java theme={null}
  // counter must be a field, not a local variable
  int counter = 0;
  LazyCell<Distance> lazy = new LazyCell<>(() -> {
  	return Distances.mm(++counter);
  });

  lazy.get(); // now counter is 1, this is equivalent in mm
  lazy.get(); // still 1
  lazy.invalidate();
  lazy.get(); // now counter is 2
  lazy.get(); // still 2
  ```

  ```kt Kotlin theme={null}
  // counter must be a field, not a local variable
  var counter = 0;
  val lazy = LazyCell {
      (++counter).mm
  }

  lazy.get() // now counter is 1, this is equivalent in mm
  lazy.get() // still 1
  lazy.invalidate()
  lazy.get() // now counter is 2
  lazy.get() // still 2
  ```
</CodeGroup>

# InvalidatingCell

Invalidating Cell is like lazy cell, but has a built in self invalidation
function as well.

<CodeGroup>
  ```java Java theme={null}
  InvalidatingCell<Distance> invalidating = new InvalidatingCell<>(() -> {
  	return Distances.mm(++counter);
  }, (self, contents) -> {
  	return contents.lessThan(Distances.mm(10)) || self.getTimeSincelastSet() > 1;
  });
  ```

  ```kt Kotlin theme={null}
  val invalidating = InvalidatingCell({
  	(++counter).mm
  }, { self, contents ->
  	contents < 10.mm || self.timeSincelastSet > 1
  })
  ```
</CodeGroup>

Whenever the contents of the cell are accessed, the invalidating function is
checked, to see if the cell should be re-evaluated.

The cell contents should not be accessed through the `self` parameter, as this
will cause stack overflow, this is what the `contents` parameter is for.

## StaleAccessCell

A time-based wrapper for InvalidatingCell.

<CodeGroup>
  ```java Java theme={null}
  StaleAccessCell<Distance> staleAccess = new StaleAccessCell<>(5.1, () -> {
  	return Distances.mm(++counter);
  });
  ```

  ```kt Kotlin theme={null}
  val staleAccess = StaleAccessCell(5.1) {
  	(++counter).mm
  }
  ```
</CodeGroup>

This example will invalidate when it has been 5.1 seconds since last access.

## StaleEvalCell

A time-based wrapper for InvalidatingCell

<CodeGroup>
  ```java Java theme={null}
  StaleEvalCell<Distance> staleEval = new StaleEvalCell<>(5.1, () -> {
  	return Distances.mm(++counter);
  });
  ```

  ```kt Kotlin theme={null}
  val staleEval = StaleEvalCell(5.1) {
  	(++counter).mm
  }
  ```
</CodeGroup>

This example will invalidate when it has been 5.1 seconds since last eval.
