3 ms·
> The calls are not yet made—we’re only building a blueprint of those calls: <alert> <concat> Hello, <prompt>Who are you?</prompt>
by wavemode 2y ago
> The calls are not yet made—we’re only building a blueprint of those calls:
<alert>
<concat>
Hello,
<prompt>Who are you?</prompt>
</concat>
</alert>
> This blueprint of “potential calls” looks code, but it acts like data. It’s structurally similar to function calls but it is more passive, inert, open to interpretation. We’re yet to send this blueprint to the other computer which will actually interpret it.
You've reinvented Free Monads: https://www.haskellforall.com/2012/06/you-could-have-invented-free-monads.html https://www.haskellforall.com/2012/06/you-could-have-invente...
That article is a bit dense if you're less familiar with Haskell, but the basic idea is that you can write code that looks like:
do
name <- prompt "Who are you?"
message <- concat "Hello, " name
alert message
And what actually gets assembled is something resembling a syntax tree of operations, waiting to be interpreted.
You could interpret it locally, or have the interpreter send requests to another computer. And (if such are your desired semantics) the interpreter can short-circuit the whole thing and return an error message if any step fails - similar to how you describe these as being "potential function calls", i.e. calls which as of yet may or may not successfully execute.
Analogously, JavaScript already has a monad-like construct which can achieve something similar:
async () => {
const name = await prompt()
const message = await concat("Hello, ", World)
const result = await alert(message)
return result
}
But this is pure code, rather than data that can be interpreted in a custom way - it will always be "interpreted" by the runtime itself. The Haskell example is somewhat of a blend between data and code (it desugars to a tree of closures calling each other in sequence, which you have a lot of control over the execution of).
Your React-style example attempts to make this concept into pure data. Though in some ways, a DSL becoming pure data wraps around and becomes pure code again. You need to parse it, semantically analyze it, and then execute it - in other words, you've invented a compiler.
- alexisread 2y agoInterestingly Wat (https://github.com/manuel/wat-js https://github.com/manuel/wat-js) handles Dynamic Variables, which fit well with serialized code, in that the serialization boundary can be better partitioned into variables you need to serialize (locals etc.), and environmental (dynamic) variables which are subject to their runtime env. Wat also happens to have a good concurrency model, and a portable bytecode. Worth looking at in this space.
- danabramov 2y agoThanks for the context! I give Haskell a one-word shoutout in the article as a hint but I really wanted to take the reader on the journey of inventing some of these things themselves.