3 ms·
Xena is right to note that this simple state-transformation function, f(event old-state) -> [actions new-state], is the obvious and eternal way to build a serve
by yarvin9 11y ago
Xena is right to note that this simple state-transformation function, f(event old-state) -> [actions new-state], is the obvious and eternal way to build a server. It's also worth noting that it's basically Haskell's State monad.
Whatever you call it, it's a design pattern, not a system service. Urbit on the outside, as an "operating function," is defined by the "universal design." But since it's a pattern rather than a service, it will tend to reappear at each layer of a layered system. Urbit on the outside uses this pattern and so do Urbit applications, but these are very different layers of Urbit.
At the application layer, a command to an IRC daemon is a great example. There still seems to be a good deal of boilerplate in the Lua code presented here. The attraction of the "universal design" is the goal of eliminating all, or almost all, boilerplate code in a network server daemon.
How would one go about that? First, be a single-level store, so the daemon is automatically a database. Second, make application messages are transactions with end-to-end acknowledgment, no return value, and exactly-once delivery. The message is automatically deserialized and validated, and passed to the application as a simple typed argument. If there's a problem with the operation, just crash; the result is delivered as a transaction failure with an annotated stack trace. Also, messages should be sent over an encrypted P2P network and authenticated by scarce, memorable identities...
On the other hand, I'm sure the Lua daemon is a lot faster!
- jwatte 11y ago(Event, State) -> (Actions, NewState) is indeed how Erlang/OTP applications and components have been structured for the last 20 years! Concrete existence proof.