Blog

Let That Async In

Phase One 22 May 2026

If a Program just runs straight through from start to finish, how does it cope with anything that does not finish straight away, a web request, a file read, a slow computation?

The trick is that the values flowing around a Program are not bare numbers and strings. Each one is a small structure: the underlying value, plus a little metadata wrapped around it.

value "Hello" ready no error none
Every value is the data plus a little metadata. Readiness and errors ride along and propagate by themselves.

The most important piece of that metadata is whether the value is ready. When I fire off a web request it returns immediately, with an empty or default value, marked not-ready, so the program can keep running. Every calculation knows how to handle this: if any of its inputs is not-ready, its own output is marked not-ready too, and that status quietly propagates through the graph on its own.

Where it finally matters is at the edges, when a value is about to be shown. The interface has a piece, call it the loader, that watches whether anything it depends on is not-ready, and if so shows a spinner over that region instead of the half-finished content. The same metadata carries error information, so the spinner becomes an error message, with a retry, when something fails. You wrote none of that; you wrote the happy path, and the readiness came along for the ride.

An honest edge

It is not entirely free of sharp corners. A couple of constructs - the ones that branch or iterate, like an If or an "each" over an array - don't themselves know about the interface, so when their condition or list is not-ready they need a way to tell the loader that something is pending, rather than just rendering nothing. Today that is handled as a small special case; the more general answer probably lies in mode-based programming, where a construct can take on knowledge of the contexts its content emits into. That part is still being worked out.

← Back to the blog