When people talk about how their favorite FP language is not OO, it raises my hair a bit and wonder what kind of code this person produces. A Clojure programmer will throw out some multi-level map reduce that abstracts over arbitrary sequences and then jam an ordered tree map into it, and claim it's not OO. And I'm like, what do you think polymorphism and encapsulation are?
I guess my wording is not entirely accurate. I meant OO-class-based-inheritance and OO-class-based-encasulation-of-state.
> I'm like, what do you think polymorphism and encapsulation are?
Well, when writing Haskell I'm not dealing with object instantiation, OO-classes and OO-subclassing. I have no problem with encapsulation per se; it is an important tool of creating abstractions needed to reach any kind of productivity. It is more that the OO-style of encapsulation is no longer something that I believe works in the long run. In popular Haskell terms "it does not compose" or more lay-men terms "its likely facilitates creating a lot of maintenance burden".
This leads to both a narrow idea of what OO is (mostly limited to the way those languages differed from C), and the idea that OO is incompatible with FP (because early Java and C++ had poor FP features, even though some earlier languages in which the OO paradigm had been supported had much stronger functional features.)
I think what the person you're replying to is saying is you actually are. You don't literally write "Foo x = new Foo()" but that's just a syntactic feature of some language. Haskell has types and classes and sub classes. You just don't write them the same way.
In the theoretical sense OO and FP share some concept like encapsulation and polymorphism. But a class in C++/Java/Ruby is whole other thing then type-classes in Haskell.
First, Clojure is very much inspired by OOP (with actual OO features). It has not one, but two subtype polymorphic dispatch mechanisms ("virtual dispatch" in OOP parlance): multimethods and protocols. These aren't just any features. Much of Clojure's functionality and design is built around protocols, which is just your plain-old OOP polymorphism. So some OOP concepts are not only present in Clojure, it is central and essential. OCaml, of course, is also FP and OOP, as is Common Lisp.
Second, what you call FP'isms have been part of OOP for about 40 years now, and not only Smalltalk. Closures were a planned feature of Java 1.0, but were dropped because of deadline considerations[1]. In fact, most features you associate with FP were very well known when OOP came about.
So OOP and FP have never been in opposition to one another. Just sets of features that you can choose from. The thing is, that in spite of having some sharp corners, OOP has proved very apt as a paradigm for building large maintainable system. In fact, we know it's done a much better job than the previous prevailing paradigm of structured programming, that we can't be sure whether OOP's "downsides" are anything particular to OOP or simply a result of any imperfect paradigm that has achieved such wide usage by programmers of a very wide range of skill and experience.
As to non-OOP FP, it is quite possible that much of its allure is nothing more than its relative novelty to developers today, and that it hasn't yet suffered much abuse in the hands of inexperienced programmers. But we don't yet know whether it would fare as well as OOP in the development and maintenance of large, long-lasting software.
It's best, I think, not to be too dogmatic about these things. OOP has some great ideas, as does FP. Both have their shortcomings.
My admiration for Clojure comes not from its abandonment of OOP (because, as I've explained, it didn't completely abandon OOP), but its very wise selection of features from both OOP and FP, while keeping the language very simple and incorporating some very interesting new ideas (all shared data is immutable/transactional). It does remain to be seen, however, how Clojure fares in large projects over time.
[1]: http://www.blinkenlights.com/classiccmp/javaorigin.html
Rich Hickey did say that the big problem with OOP is only that OO languages mix many concepts together (identity+state+polymorphism+encapsulation+...etc) and that Clojure has all of these things, but separated out into their individual pieces, so that the programmer can choose which of them make sense to the problem at hand. Basically, that the ideas behind OOP are good, but that you should be able to choose just the bits that make sense for the situation you are in and not pay for the ones that don't (eg in terms of complexity or understanding).
That's true, even though OOP as a paradigm was articulated before FP was (both paradigms were prefigured by less-structured practices in programming, before either was articulated as a programming paradigm, so the techniques of both existed before either was cataloged as a paradigm.)
> So OOP and FP have never been in opposition to one another. Just sets of features that you can choose from.
OOP and FP aren't sets of features, they are approaches to programming; there are features of languages which facilitate FP and/or OOP, to be sure, but the paradigms aren't sets of features.
> As to non-OOP FP, it is quite possible that much of its allure is nothing more than its relative novelty to developers today,
I doubt it; non-OOP FP has been around almost as long as OOP has been, has frequently played a fairly central role (whether or not it was explicitly named as a paradigm) in computer science in education, and, in any case, and it became popular when domains where it particular implementations of it had long been proven (particularly, concurrent/distributed systems) started becoming part of the problem space of mainstream development.
The idea that its popularity is driven primarily by novelty doesn't seem like the best explanation.
Yes, but not a big role in OOP's home court: large systems with long lifespans.
> The idea that its popularity is driven primarily by novelty doesn't seem like the best explanation.
I didn't say that. I said that the low number of reported problems is likely a result of it not having seen much actual combat and coming under heavy enemy fire just yet (namely, large projects, maintenance over many years, some by inexperienced programmers). It's still fresh out of basic training (in comparison to OOP). OOP also seemed almost perfect for quite a few years.
I use Clojure professionally, and CLOS is easily the thing I miss most.
Most of those FPisms (LINQ) are already present in Smalltalk.
The real problem comes from completely ignoring data structures. By mixing in functions with data, proper data structures are virtually nonexistent in the OO world and manipulating data properly becomes an exercise in frustration and working around the limitations of the OO implementation (data that should be together isn't; data that shouldn't be is; easy access to the data, etc.). In this regard, I'd say procedural programming is on roughly equal footing with functional programming in as much as they both tend to focus heavily on data structures first. As they say, show me your data structures and I don't need to see the code; show me your code and I won't know shit.
Your point that OO's main advantage is popularity is spot on. It certainly is possible to build large, maintainable systems in an OO fashion, but it is very difficult and requires a lot of experience. That's why there is so much terrible OO code out there. It's virtually impossible to write decent code without a lot of experience. This mammoth learning curve is not as steep in languages that focus on data structures first, whether they be procedural or functional.
For me understanding the greatness of FP was build on the understanding that there are no "benefits of OO".
Once I realized that the "abstractions of classes and inheritance" and "encapsulations of state in objects" (and other OO-paradigm pillars) where harmful, I started truly researching the alternatives.
I could go back to C --imperative, state-all-over-the-place, self-managed memory-- but it seemed like an impossible step in web development.
Quickly I found promise in languages like Clojure and Haskell. High-level enough for web development, yet faster them my trusted Ruby code, and seemingly more maintainable.
The main benefit of OO I know experience is it's popularity. Going from Java to Ruby is a lot easier then from Ruby to Clojure or Haskell. The good news: many OO languages are incorporating FP'isms, and allowing a functional approach to solve problems, this helps FP like myself newcomers quite a bit.
TL;DR: I came to the realisation that the benefits of OO where mainly theoretical and did not hold in practice. Main 'real' benefit of OO is its popularity.