There's no denying its power, and I'm sure it's superior for some applications, but the inherent mixing of persistent state and behavior in objects is pretty much irreconcilable with functional programming as I understand the latter.
For example, to me perhaps the single most useful OOSE artifact is the sequence diagram (UML version here: http://en.wikipedia.org/wiki/Sequence_diagram); in the non-side effecting functional programming world you have much less to keep track of in that manner.
To me, the biggest advantages of OOP are composition and sub-typing. Check out PLT-Racket's concept of an iterable versus that of most OO languages (http://docs.racket-lang.org/reference/sequences.html#%28def....). In PLT-Racket you have to bundle together a list of functions, essentially rolling your own v-table from scratch. In an OO language you have this nice packaged concept of an Iterable interface, which is much easier to understand conceptually.
Underneath the hood, both are doing the same thing; both are performing operations according to a specified interface for some underlying data that the consumer knows nothing about. This is encapsulated message passing, which is at the heart of the OO. The same sort of thing can be done with immutable objects like functional data structures (http://code.google.com/p/pcollections/). OOP and functional programming need not contradict one another or be mutually exclusive.
As a final note, no one codes in lambda calculus any more than anyone codes in Turing machines. Real functional languages have mutable variables, and Haskell is the only language that I am aware of that tries to hide this fact as much as possible.
OO benefits tremendously from Functional programming. It's much, much easier to develop in a system where you can treat calling most of the methods on most objects as if they were stateless. A system that uses less state is more flexible and easily changed. A system that better encapsulates state is also more flexible and easily changed.
There will be new "patterns" on how to use both features without shooting yourself in the foot. There will be new libraries written that exploit the awesomeness of both features. At the end of the day, there will be people benefited from that, and there will be more segmentation in the industry. People will have to be trained (wait... that no longer exist in our industry).
... and I... I will move on to a more managerial position so I can put to rest the learning of programming language for the sake of learning and swinging ego than for actually building things.
http://en.wikipedia.org/wiki/Common_Lisp_Object_System is probably a good place to start
Compilers are just functions from input to output, so it is easy to write them in a functional way. For example code formatter, report generator, any program in which we are only interested in the final result, not in the intermediate steps, and nothing "new" can happen in the process of computation.
Interpreters are more imperative by nature, and it is more natural to write them in imperative way. For example real-time simulations (including games), interactive apps like offices suites, crud apps, etc.
In interpreters functional programming can be used in the small scale, to implement commands, but the result will be imperative interpreter with state and commands that modifies this state.
So oop is more suited to describe domain of most programs - users think about crud apps like this: "this button changes the name of selected student", "this button deletes student from base", "this button assigns student to course". Even if under the hood there is functional code, it is in reality interpreting imperative language and operating on state.
At least that's how I see it. YMMV.
For instance, in Clojure I could write a multimethod that updates refs of type Student, and Course:
(defmethod assign [Student Course]
[student course]
(alter student update-in [:courses] conj course)
(alter course update-in [:students] conj student))
There is polymorphism and mutability here, but we're not dealing with objects.So to rephrase my question: what are the advantages of OOP when dealing with mutable state?
Great insight. Thanks for teaching me about this.
Works good till you reach a problem domain it's not appropriate for.
Models are great till you take them for reality.
I've often thought that the recent emphasis on functional languages stems from the fact that webapps are where a great deal of innovation has been coming from lately. The design of the HTTP protocol makes it particularly straightforward to think about server-side code as a series of stateless (ignoring the database) transactions. The "model" of inherently* functional tasks as compilers and inherently procedural tasks as interpreters does a good job of crystallizing this idea.
(* When I say "inherently" functional or procedural here I mean tasks that lend themselves to being expressed cleanly one way or another.)
The best approach appears to me to be taking the best of both worlds. Functional may solve lots of problems, but you can't deny the advantages of a good OO design. Just devise your OO architecture for good reusability, flexibility, low coupling and high cohesion and then just use the best that functional programming has to offer.