Calculations

A calculation derives a new reactive value from existing ones. Reactive.Calculate is the primitive behind it. You rarely write it by hand; modules like Reactive.Maths are made of calculations, so you usually compose those. It is worth seeing, because it explains how the forward direction works and why Reactive folds “asynchronous” into the same idea.

Value, inside the closure

Because every value is wrapped, arithmetic on one directly is unavailable. Reactive.Calculate gives you the one place where raw values are safe: it takes a closure that runs as ordinary native code. Inside it, Reactive.Value(x) unwraps a reactive input to its raw value, you compute in plain JavaScript, and you return a raw result.

const celsius = Reactive.State(Maths.Real)(20);

const fahrenheit = Reactive.Calculate(() => {
  const c = Reactive.Value(celsius);   // unwrap to a raw number
  return c * 9 / 5 + 32;               // native maths, return raw
});
Deriving Fahrenheit with a calculation

Value and Calculate belong together: Value attaches to the calculation that encloses it. Inside one, every input you read through Value is recorded as a dependency, which is what makes the next part work.

Readiness propagates

Because a calculation knows exactly which inputs it read, it also knows their readiness. If any of them is locked (not ready yet), the calculation's result is locked too, so your closure's value stands in only for data that is present. The lock flows forward through every calculation built on top, without a line of code from you.

1

An input isn't ready

A value is locked, perhaps still arriving from the network.

2

The result locks too

Any calculation that read it is locked in turn, and so is anything derived from that.

3

Then it clears

When the value arrives, the calculations recompute and the locks fall away.

This is why Reactive unifies synchronous and asynchronous values. A figure waiting on a request is not ready; everything computed from it is not ready; the page shows that pending state; and when it resolves, the same calculations run again. You write identical code either way, and the framework tracks whether something has loaded.

Composing with modules

You rarely reach for Calculate to do arithmetic, because the maths operations are calculations already. Maths.Real.Add, Multiply and the rest each take reactive values or plain constants and return a reactive value, carrying locks through for you. Compose one operation per line:

// fahrenheit = celsius × 9 ÷ 5 + 32
const scaled  = Maths.Real.Multiply(celsius, 9);
const ratio   = Maths.Real.Divide(scaled, 5);
const reading = Maths.Real.Add(ratio, 32);
Composing the same formula from module operations

The constants 9, 5 and 32 sit right beside the reactive celsius; each operation takes them as they come, treating both alike. The same operations run backward inside a reverse; that is exactly how the two-way Fahrenheit field on the reversibility page is built.