The Java blogosphere is currently discovering or introducing to the uninitiated the benefits of closures. To me, posts like Reginald’s seem to present closures as an advance from OO. This is kind of strange, given that the historical order is exactly the other way round!
When I started digging into OO languages in the 90s, I had already spent some time with Scheme and Tycoon (a language based on Luca Cardelli‘s Quest), all of them higher-order functional-imperative programming languages. I did some non-trivial compiler programming in both languages, and it certainly was fun, in a way similar to solving math riddles.
I learned that OO was great because it names things. OO allows a traceable connection between the conceptual design level and the implementation level. Concepts have names, so you can talk about them, between programmers and architects. The promise of OO was to replace the dazzling complexity (and intellectual challenge) of functional programming with something more manageable.
Language is not understood best when you have removed as much as possible. Would you rather read a novel, or an algebra textbook? Just imagine taking your green, yellow and red pen and marking up a book by Neal Stephenson.
Conciseness comes at a price: The more compressed your code, the harder it is to understand what the consequence of some change would be. If you have left out everything you do not need for your current goal, what if the goal moves? If (e.g.) you find that what was once a closure should now be a class, e.g. because some code wants to inspect it instead of just running it, you’ll be crying for another super-advanced refactoring IDE.
“Everyone knows that debugging is twice as hard as writing a program in the first place. So if you’re as clever as you can be when you write it, how will you ever debug it?” (Kernighan)
Higher-higher-order functions and inferred types, or lists of lists of pairs whose cdr happens to represent some concept (except when it represents another concept) will all give you that occasional “ouch, there’s a error message, but I don’t think there should be!” The code looks fine, so why does the type checker not like it? (it probably took something you wrote, took it all wrong, drew impressive conclusions and is now reporting a problem at a completely different place). The program state and the code both look fine, but they differ in the level of nesting of some unnamed construct (e.g. a closure or a list where a value was expected).
I strongly associate higher-order functional programming with long stretches of uninterrupted concentrated programming work, and single-person projects. In contrast, OO gives you a pragmatic, shallow paradigm for making software intelligible and available for cooperation.
Closures can be a nice tool for creating your own DSL, to make your code get closer to the design model. But closures can also take you further away from the design model, by creating constructs that only make sense in the abstract.
Object-oriented programming was introduced to fill a need not satisfied by functional and imperative languages. Remember: Going from functional to OO is an advance.