> but probably not practical in reality.

Thats how I've been building UIs for the last few years. `re-frame` in ClojureScript for one is a fantastic framework built on top of these concepts.

> I don't see the point of having a debate about the merits of functional programming vs. OOP in the middle of your post

I made that distinction to highlight the differences between retained-mode UIs versus immediate-mode UIs. There are more similarities to OOP vs FP than differences here.

Think of it this way; the application itself already contains all the state it needs. A retained-mode UI will deep copy that state into the UI components while an immediate-mode UI will make the UI state a function of the application state. There is huge value in doing that because it dramatically simplifies the UI stack, this translates into shorter iteration times, simpler reasoning and less bugs. Its no good thinking about higher level tooling if the fundamental API is overly complex.

> unless you build a system that's easy to understand on that end as well

We shouldn't care about whether something is easy or difficult; we're only going to learn it once after all. We should instead care about whether its simple or complex, because that is a direct function of our ability to reason about things once they are learned. Most things that are easy to learn generate more complexity than simplicity and I believe this is harmful in the long term.

> I don't think it's unreasonable to expect that the low-level rendering engine (ie. an implementation in UIKit) maintains some level of UI state.

You're right, its perfectly reasonable and precisely what React does under the hood. Where I disagree is that I don't want the cached UI state to leak into the components. Just like the current state of the DOM is irrelevant when rendering the virtual DOM. Its purely an optimization mechanism and one which should be allowed to evolve independently from the higher level components.

> Things generally aren't immutable

Then why are so many things moving towards immutability? Modern video game renderers push really hard to be stateless, to be completely decoupled from the game threads, to not leak cached state into entities and a bunch of other FP-inspired concepts.

The end result is incredibly more parallelism. The rendering pipelines are much simpler and performant. There are quite a few advantages to this approach. It also generates optimal memory layouts and accesses, these are simply emerging from such a design. Its much easier to have linear memory accesses if you constantly recreate the display lists in fresh memory. Updating a state tree is much more complex than creating a display list and it greatly cripples the potential optimizations.

> higher level libraries can easily remove the pain of UI state management

That is not the feeling I get when I look at the average React project; most components use getState/setState, need to touch the virtual DOM for almost every operation, are needlessly maintaining two views of the same state (app and UI) and whatnot. Or they go full Functional Components and the result is a huge stack of component layers from hell.

> It seems to me the appropriate abstraction is build the protocol around a UI state tree

I believe this is fundamentally wrong; the appropriate abstraction should be built around the application state. You can derive UI state from that, and doing so liberates you from having to maintain the UI state independently.