Deterministic Core, Non-Deterministic Shell(outdata.net) |
Deterministic Core, Non-Deterministic Shell(outdata.net) |
Here is an example of a calculation written imperatively. It remains easy to reason about because the actions don't leak out of the function:
function add(ns) {
let total = 0
for (const n of ns) {
total += n
}
return total
}
On the other hand, a deterministic state machine like `a = AddMachine` is harder to reason about because it still matters how many times the action `a.transition(1)` is called. (Note it is possible to implement the state machine as calculations.)https://ericnormand.me/podcast/what-is-an-action
https://livebook.manning.com/book/grokking-simplicity/chapte...
Without that structure, code tends to be difficult to test, since the impure stuff like network requests is part of the same sequence of statements as the logic you want to test. (That is: pure code is easier to test (but harder to write real programs with).. so, "arrange the code so you've got a well tested core" is a good strategy).
The nice part about the pure/functional is that you know for the same inputs, you always get the same outputs. -- I think if you want to say, "well, this stateful object is still pure (if you consider the state part of the input" then sure, I guess.
So I’d implore the author to delete this restriction. Even when randomized algorithms produce different outputs (the treap giving you differently shaped trees with the same sequence of inserts) these outputs have properties that can be checked statistically.
If you really want true RNG, you can inject a deterministic RNG at test-time and use a real one otherwise.
That’s why as a matter of practicality I’d advocate otherwise.
Idk. I like Gary's formulation. No, I love it. One time when designing an STS with Claude I told it my FCIS design for an STS and Claude demonstrated real excitement -- it really loved the idea.
Briefly, my idea was to have the functional core isolated such that it receives a JSON description of the input request, any additional data [wait for it], and outputs either: an error, a request for more data, or a description of a token/credential to issue and with what issuer credentials. This would allow one to write all the core logic in Julia, JS, MicroJS, jq even, any language you like, and the imperative shell is what does all the rest (authentication, token validation, database lookups -- whatever you want). I swear Claude expressed real excitement over this. I've seen Claude be frustrated as well. It really does seem to have some sorts of emotions.
But essentially a component receives a list of high level instructions / description of what the user wants done, and it translates that into descriptions of "lower level" commands that should be performed. And those commands then get executed separately.
Anythinf statefule / io is contained in the commands and can be tested easily with external dependencies. And the complex logic is all pure in decided what to do and how to do it based on what was asked for.