These are chat archives for mithriljs/mithril.js
I distinctly remember you talking about your vdom queries with the proviso that immutability was too expensive to be worth it
That's because I did :D
My weird interpretation for vdom trees uses mutable lenses because there's no point paying the perf cost at that point in the app lifecycle. It's totally fine to mutate the vdom itself because its created from scratch everytime.
But not because it's too expensive to be worth it, it'd probably be fine if it were immutable. But because there's no benefit to immutability there.
Immutability is only useful if we are sharing state. If there's no sharing, then mutable state is in effect immutable from an application perspective. Because if state changes in an application and no-one's around to see it, did it actually change?
The key reason immutability is so useful (beyond all the other subtle things you get), is code in completely disparate parts of an application can reliably share state without any detriment to maintenance or stability. If on the other hand, anyone can mutate the state tree at anytime you need to be judicious with how things are updated and when and who by. That leads you to proxies, and getter/setters and a lot of manual null/type checks because of mistrust of the state tree and other areas of the codebase.
Part of the value in something like typescript is, you can say, this tree has this shape, and if you want to modify it you have to adhere to the types of properties and structures on that tree. So that saves you from 1/2 the problem. It'll warn you if a value is null, it'll warn you if the type your module expects a value to be isn't what other modules expect it to be.
But... that doesn't help with value changes. So if we have one module that pushes into a list, it might assume the list is non empty from then on. Some time later it may grab the first item. But some other component somewhere else may have reset that list to be empty and now we've got
undefined is not a function. Who changed the array? Hard to say. When did it change? No idea.
In most cases the component will just have a conditional to check it's not empty. Multiply that out to most interactions in a system with shared mutable state and you find yourself with a lot more conditionals, and quite often not enough to cover all the permutations of possible failures.
If the tree is immutable, the only way we can propagate changes is to create a new change and send it to the top of our application and have it flow down again. Now we know who changed a value, why, when, how etc. We also can retain our version of the state if we want quite trivially without having to clone anything. We can make a lot more assumptions about our state which saves us writing pointless checks everywhere.
So with all that said you can probably imagine scenarios where immutability is more suitable. And some situations where mutability is fine.
Like for extremely short lived, non shared state, mutation is fine. E.g. If state only moves in one direction and performs one task, mutation is fine, e.g. a command line application, or even some HTTP requests.
But in user interfaces where we have long lived shared state, immutability is incredible.