P, and all of its parents also need to have property P, then P is contagious.When can that happen?
- Exceptions bubble up through the call tree
- State has to be lifted up to the root of a call tree
- If a function is
async, its ancestors must be too - Centralized services also centralize any decentralized services that call them
- In a physical system, if you know the position and momentum of an object
Aand it collides with another objectBthat you don’t know one of those quantities for, then you no longer know them aboutA. (caveat: I’m no physicist)
async function a() {
// a has to be async to await b()
await b()
}
async function b() {
// b has to be async to await c()
await c()
}As a programmer, that seems bad. Bubbling up breaks encapsulation and makes things harder to compose. If I have a nice application and need to mark a function deep in the app async, why do I need to update all of its callers to be async too? Why should a parent know about its grandchild?For good reason. At runtime, some contagious things are special:
- Exceptions bubble up through the call stack
awaitpauses execution
- Asynchronous code needs to be awaited before continuing. As a consumer of an asynchronous function, you want to know that it’s asynchronous so that you can treat it as special.
- State is a function parameter, because the function’s computation depends on it. As a consumer, you need to pass the state to it.
- Functions that throw are modeled with a
throwsclause,Either,Err, or nothing, depending on the language. As a consumer, you might want to know that something throws so you can handle it.
- Async:
Future/Promise - State: The
Statemonad, or passing a callback down the call stack - Exception:
Either,Err,throws
- Async:
.then, React suspense boundaries - State: Mutable state, React local state
- Exceptions:
try/catch, React error boundaries
What unites all of those? They’re effects, that different languages model differently. Some languages keep them implicit (like
throw in languages that don’t have throws clauses), some make them explicit (the State monad).There’s nothing inherently contagious about these things, as evidenced by the languages that support trap doors for them. It’s up to language designers to say “this thing should be contagious” or “this thing shouldn’t”.
What should be contagious, but isn’t? What is contagious, but shouldn’t be?
/philosophy/of/programming/2019/09/08/On-Contagion.html