All this is saying is you can't compose behaviors because we insist on having only one whole state, and only one concept of what 'next' state is.
If you can have state with sub-states and 'next' operator that is respective to what sub-state we want to address then this example is easily composable.
But then of course you might want to have substates interact with each other so it complicates further. It just looks like multithreaded programming.
I got that, my point is that such composability is rarely better than good old OOP with encapsulation. Enumerating all possible state transitions on object interface leads to better design than procedural programming (and composable operations are procedural programming).
Its composability is a bit of a double edged sword. While it leads to a more declarative style of state management, I've found our implementation of it to lead to confusion about when /where/which states are swapped in or out. But honestly I think anyone can have a great or cruddy experience with any state management library depending on how it's weaved into the code, and I don't blame the library so much as I blame our implementation thus far.
Code that does I/O has a lot of interplay that's hard to replicate and impossible to cover entirely. The physical world is nothing but shared mutable state.
Yes, that was actually my point. State is essentially function composition. Thus I'm arguing for avoiding dependencies between conceptually independently compositions.
When you have state...I mean real state, it sure is nice to encapsulate that state in an object rather than in what is basically an unencapsulated monad. OO supports state encapsulation, pure FP basically does not, that is a big deal. Immutable programming sort of side steps the issue, that state is needed at all, that an interactive program can somehow be stateless is ridiculous, even many batch programs require some form of state (even if it is unencapsulated in a monad).
Your 60-line function decomposed into nice small parts using beautiful composable abstractions is an FP pipe dream. Yes, if the problem is well understood, someone has thought about it for a long time and has come up with some beautiful abstraction that works for a narrow set of related problems. Now, as soon as you venture outside of a well-understood/nice abstraction domain, your code is just as bad in FP, if you can figure out how to implement at all.
Yes mathematically composability is part of it. That's because math functions return the same type. Its easy to express the 'state' of a function as the value of the operation.
There's a wider idea of idempotency in computing - that state changes in general respond to operations. Repeating the same function more than once (because the network stuttered or the sender resent the message) and arriving at the same state is a common example.
The argument is that we don’t compose enough functions to create value. Instead, we lean on (not always well defined) state, the result of operations on data
RE 2 do you mean you don't need to have mutable state to have objects? Unless I have a huge misunderstanding of what you mean by 'state', it seems like state is necessary for objects to exist..
>> Immutable state can be a huge pain in the ass. A common mistake FP beginners, and even "experienced" developers, make is the creation of this complex jungle of entangled functions.
The two challenges past this point are (a) making the components ignorant to the larger structure of the single state enabling things like component-local state and state representation independence and (b) getting creative with how to construct reducers composably so that various domain concerns are separated from one another in the construction of the core state.
You can't build products without mutable state. How far should we go when we reason about global mutable state? Do we go as far as the database layer? Computers are state machines and I don't know why we're so eager to get away from that. Separation of concerns and interfaces/protocols help, but somewhere down the line, it's accessible, mutable, and it's stateful.
It's a complex topic. The thing is that sequential mutable state doesn't scale, and you'll quickly have to introduce routines, modules, objects of whatever to have some control over side effects. The natural aspect of a list of instruction is exhilarating for many but is also rope to hang your self because you won't try to separate concepts and scopes since everything is accessible. So much stuff just doesn't happen when you don't use this paradigm. Instead of drowning in state variable improperly synchronised, you suddenly rise above and start rewriting trees.
It is important to note the difference between state and mutable state as I believe you are conflating the two here. There is no reason that you cannot have structs.
reply