Reverse
Reactive.Reverse takes the type, then the source and the block.
Reading the reverse reads the source. Writing it runs the block. The callback argument is the value just set.
Reactive.Set in the block stores that write on a state.
Celsius in state, Fahrenheit on the input
The state holds Celsius. The forward calculation turns that into Fahrenheit, and that result is the source of the reverse. The Fahrenheit input shows the source. Typing in it runs the reverse, which stores Celsius. The Celsius field writes the state directly, so editing either side updates the other.
const celsius = Reactive.State(Maths.Real)(20);
// convert Celsius to Fahrenheit
const scaled = Maths.Real.Multiply(celsius, 9);
const ratio = Maths.Real.Divide(scaled, 5);
const fahrenheit = Maths.Real.Add(ratio, 32);
// convert Fahrenheit back to Celsius on change
const fahrenheitReverse = Reactive.Reverse(Maths.Real)(fahrenheit, (written) => {
const adjusted = Maths.Real.Subtract(written, 32);
const scaledBack = Maths.Real.Multiply(adjusted, 5);
const next = Maths.Real.Divide(scaledBack, 9);
Reactive.Set(celsius, next);
});
Layout.Row(() => {
Input.Number(celsius);
Content.Text(" °C");
Input.Number(fahrenheitReverse);
Content.Text(" °F");
});fahrenheitReverse reads fahrenheit. Writing it sets celsius. Forward is Celsius × 9 ÷ 5 + 32. The block subtracts 32, multiplies by 5, and divides by 9.The two directions
The three lines before the reverse are the forward direction. They run whenever the program runs, and
fahrenheit is the Fahrenheit the field shows. The block is the reverse direction. written
is the Fahrenheit just typed. The block builds the Celsius for that Fahrenheit and sets the state. The next run
computes fahrenheit again from the stored Celsius, and the field shows it.
The Fahrenheit field is the same Input.Number as a field bound to state. It reads a value and
writes a value. Here the value is the reverse, so a read shows Fahrenheit and a write runs the block.