Now I'll be damned is that shit isn't exactly the state monad.
You're looking pretty damned to me. Monad talk is seriously mathematically rigorous, so you'd need to be able to tell me at least where the functor is and where the unit and join are. I can do those for the state monad as it appears in Haskell, but unless you're a much better squinter than me, I can't see it here.
The main flaw of OOP isn't data rigidity, and I hope other folks with OCaml experience can chime in on that one, but
STATE. It's all about state. Objects complect state, identity and value. They tie behavior to state. They're a mess. Message passing is better and solves half the problems (smalltalk, erlang, akka), but immutability solves all of it.
Ya'll niggas got to read Out Of The Tar Pit
I'm an Ocaml folk, but don't know how much I can chime in. Just about everything I've seen described as OOP I've found to dislike, but I've seen the term "OOP" applied to such wildly different systems that I can't point to any single thing that bothers me.
It's not the mutability. I use mutability (sparingly) even when not using objects. And Ocaml has an object system, but you can use it immutably.
What I dislike in statically typed languages is the fucking subtypes. This is the property of your type system where a value can have multiple static types, with the static types arranged in a lattice. It's the "is-a" relationship. A cat
is a mammal, meaning that if you have a value that the type system judges to be of type cat, it should simultaneously judge it to be of type mammal.
I don't like this. It nearly always breaks global type inference, and it really complicates generics: in C# and Java, that complication appears as type bounds on generic parameters. In Ocaml, Kotlin and Scala, it appears as variance annotations. These are noisy and annoying. And it's not that I'm not smart enough to grok variance. I have to do that anyway whenever I think about functors (in the category theoretic sense), and there I notice that subtype variance is just the peculiar variance that comes when mapping and comapping inclusion functions (i.e. coercions).
And the touted benefits of subtyping seem to be things I get better elsewhere. The standard use cases of dynamic dispatch are better solved with sum types. And the standard use cases of late-binding are better solved with lambdas (objects are poor folks' closures).
Common Lisp is a different story, as is Smalltalk, where from the get-go the engineering is geared towards the programmer living in the same runtime image for years, continuously debugging and hotplugging it. That's a whole other level of mutability, but it's the reality of using a real system. In Common Lisp terms, it means that when I add a slot to a class definition in debugging, the right thing to happen is that all live instances of the class get told to reinitialize to the new class.
This isn't the wimpy world of Python. In fact, I don't know of any languages other than Common Lisp and Smalltalk that have any decent story like this, and if only OOP were identified exclusively with these languages, I probably wouldn't be so hostile to the concept.
My current project in java (a game) has an interesting performance profile that improves steadily with time. However not even all of the JIT finesse in the world can solve GC stuttering, and so I'm forced to write things in an ugly fashion —object pooling gets quite tedious when you have to pool individual vectors. I expect the same would be true of any functional language on the JVM. If consistent framerates are not a goal though, you'll probably be fine.
If you're writing a game in C++, you'll use object pools, and it's standard to only malloc between levels.
Java is horrible for games because it doesn't let you declare that your stuff belongs on the stack. You're relying on the JIT to figure out that your object lifetimes follow a stack discipline, and if it can't, you're writing code that is far far uglier than anything you'd write in C or C++.
C# has a better story.
But yeah, for high performance games, I always want to be using a systems language.