I'm going to start with a few definitions because I can see we're not using the same ones.

Functional programming: programming in a style where functions are the basic building blocks of the program and are passed around as data to other functions along with raw data, i.e. Lisp, Scheme, Haskell. (note, functional languages are not necessarily immutable).

Pure functional programming: programming in a functional style as above, with the additional insistence on not allowing mutable state at all. i.e. (no language is truly pure because side effects are a must, but Haskell comes close).

Object oriented Programming: programming in a style where objects are the basic building blocks of the program with 3 basic features, late binding, encapsulation, and polymorphism allowing the hiding of raw data behind a message passing interface so that the program is centered around object behavior rather than object data. (note neither classes nor inheritance are necessary features of OO systems, they are simply common features).

> I think you're more interested in interfaces than objects, actually. All the problems of objects - inheritance most especially, but mutable state too - aren't relevant if you're primarily interested in "pluggable behaviour", which really is an interface-oriented mindset, not an OO one.

That's a bit of a misunderstanding of both interfaces and OO. Firstly, interfaces simply define what an object looks like, it's an implementation detail and has nothing to do with OO in general. The same applies to inheritance. Inheritance is simply one means of code sharing and is not a necessary feature of an OO system, neither Self nor Javascript for example, have inheritance in their object systems. One can also build a system that is entirely object oriented without once using an inheritance hierarchy once. Code can be shared via delegation rather than inheritance.

> You can certainly go very far with interfaces, as both COM and HTTP have shown. Neither are object oriented

Again, I think you're incorrect, COM stands for Component Object Model, and most certainly is object oriented. An HTTP endpoint that supports GET/SET/PUT/DELETE is merely an object that has 4 standardized methods, it supports late binding, implementation hiding, and polymorphism, the primary features desired from any object system. Each endpoint is an object that accepts 4 messages. It doesn't have to be an instance of a class to be an object.

> I will still contend that a cyclic graph of mutable objects (whether they look like message-passing interfaces or not) makes for a very marshy foundation. The reason is mutability and lack of idempotence.

Neither of those have anything to do with OO; you can have an OO system of entirely immutable objects. Again, you're critiquing implementation details of systems you've seen that use objects and then blame objects for features those systems have that have nothing to with with OO. Just because an OO system does something bad, doesn't mean it's OO itself that is the issue.

> There's a reason I keep harping on about mutability despite accusations of straw men: it is the fundamental flaw at the heart of OO.

No, it isn't, because mutability isn't at the heart of OO. While it's perfectly valid from a functional perspective to critique mutability, it does not follow that said critique applies to OO in general. Objects do not have to be mutable, while it's common for OO systems to be mutable, what makes an OO system is not the mutability. This is again a strawman, you mean to critique mutability, not OO, they are simply orthogonal.

One of the most useful objects in systems I work on is the Money object; it's immutable, it's treated as a primitive, it's easy to reason about and won't allow things like adding different currencies together or dividing and losing pennies. Object systems contain many such objects, another one is String. Now String... well that's a very used and very useful object with a bazillions little methods on it that return new instances of String that look differently like .ToTitleCase()... again, pure OO, no mutability in sight.

> It does not.

You're mistaken, Smalltalk the language is an elegant mix of OO and functional programming. Functions are passed around to higher order functions to do work in virtually all parts of the system and nearly all standard idioms use such higher order functional programming. Here, I think you're confusing functional programming style with immutable functional programming, they are not the same thing. Lisp is a functional programming language and everything is mutable. Functional does not mean immutable.

> You have to work very hard in most OO languages to get FP right; in statically typed languages, the type system isn't expressive enough, and most dynamically typed languages default to too much mutability.

Immutability is an implementation detail of some functional programming languages, it is not a requirement. The discussion about immutability vs mutability applies to all programming paradigms and is simply orthogonal to the OO vs procedural vs functional debate.

> From several decades of observation, I have a theory that OOP programmers get caught up in a reward feedback loop around ceremony and prefabricated patterns, a quasi-religious endorphin rush from following formalisms that aren't strictly necessary to address the problem head-on.

On that we agree, but those are just bad programmers; their failures are not a critique of the OOP style itself.

> But I don't know of anything else with the same power to clarify thinking than functional composition - it levers the mind with a solid tool rather than a wobbly, lashed-together one.

I agree, but this has little to do with OO, and more to do with referential transparency. Yes, pure functions are easier to reason about than methods who depend on hidden internal state. But objects can be useful without any state at all. Smalltalk implements its conditional statements using polymorphic objects True and False, both subclasses of Boolean, and none of these classes have any state at all; their identity alone is all that is needed to implement the entirety of boolean logic purely in the library, i.e. Smalltalk has no procedural constructs like an if statement or a while statement or a for or foreach statement; it's all done with functional programming and objects.

> And objects compose to make wholes that are less stable than their parts - because they are mutable, and state spaces multiply. Mutability is always the problem in the end.

Again, since one can build a perfectly OO system out of entirely immutable objects, then obviously this critique again misses the mark and blames OO for something that simply isn't an OO thing. Yes, most OO systems have mutable state, that's an implementation choice those programmers made, they didn't have to, but they chose mutability. Your critique is against mutability, not against OO.