> Yeah exactly, I think of this as "imperative in the small" and "functional in the large". There's no real cost to local state, but there's a big cost to tracking global state.
That's the basis of what I call "faux-mutability", wherein you have an immutable type system, but all updates are expressed as mutations.
In the current docs for a language I'm working on, I give a brief example[1], but in a nutshell, you can transform an expression like so:
let x.a.b := 5
let x := set_rec(x, #a, set_rec(x.a, #b, 5))
It does prohibit[2] making arbitrary graphs, but for the use case I'm targeting this is fine.
(Also, as a prototype for how this can work, I wrote a python module[3] that implements it with the pyrsistent module.)
That's the basis of what I call "faux-mutability", wherein you have an immutable type system, but all updates are expressed as mutations.
In the current docs for a language I'm working on, I give a brief example[1], but in a nutshell, you can transform an expression like so:
It does prohibit[2] making arbitrary graphs, but for the use case I'm targeting this is fine.(Also, as a prototype for how this can work, I wrote a python module[3] that implements it with the pyrsistent module.)
[1]: https://tenet-lang.org/#how-does-it-work
[2]: Or you'd need another mechanism to do so.
[3]: https://pypi.org/project/pyrsistent-mutable/