Now the payoff - recompute the whole sheet in topological order so every formula reads fresh precedent values. Today Recalculate replaces the naive pass and stores each computed value as it goes.
Recalculate all formula cells in topological order, storing each value so later cells read the fresh result.
This is what the chapter was building toward. Recalculate computes the
topological order, then walks it, evaluating each formula cell and storing its
result before moving on. Because the order guarantees every precedent is evaluated
first, each formula reads values that are already fresh - A4 sums the inputs,
B1 reads the finished A4, and C1 reads the finished B1. The chained result
6, 12, 13 is only reachable if the order is right; evaluate C1 before B1 and
you would get a stale A4.
This replaces the naive computeAll from Chapter 3, which evaluated formulas in map
order and only happened to work when they read plain literals. Storing each value as
it is computed is also what makes reading a cell cheap afterward: Get returns the
stored value without re-evaluating. A full recalculation is correct but does redo
every formula, even ones nothing changed near. The next chapter makes editing a
single cell recompute only what actually depends on it - and handles the cycles and
errors a real sheet has to survive.
func (s *Sheet) Recalculate() {order := s.topoOrder() // includes literals; skip them when evaluatingfor _, ref := range order {c := s.cells[ref]if c.isFormula {c.val = s.eval(c.ast) // precedents already stored fresh valuess.cells[ref] = c}}}