I'll try.
By the end of the 1950's, modular programming based on procedures and subroutines had become problematic. It was hard to have large teams of programmers working on parts of the code at the same time, and it was hard to create large well-structured programs.
The answer in the 1960's was to break down a problem into pieces, then sub-components, then subroutines through functional decomposition. This better allowed large problems to be understood, and worked on by different teams at the same time. This approach is known as structured programming.
This approach has resulted in quality software over the years, but suffers from painful limitations. One of the big ones is that as one works on a problem and discovers its requirements, the decomposition used needs to be modified, often from the top down.
Object orientation (much as for the "data" movement) represented a different way to approach a problem. Let's break down a large problem or system into entirely independent concepts that know how to to do things themselves. Let's not orchestrate concepts (objects) centrally, but instead have them do things themselves together to solve a problem. This comes close to the way we think. We recognize and organize things in our minds around us as objects. We differentiate between them by their attributes, and we classify them. When we see a tree we recognize it as such, and differentiate it from other by its attributes and also by its place in the hierarchy of types of trees we know. Behavior on the other hand is only immediately important to us if it is causal - for example if it threatens us. That unknown thing moving fast towards you prompts changes in your body, but once you recognize the object is a beetle and not a spider, you change.
Hopefully that helps.
OOP lets chunks of functions share state and hide that state from the wider application. More importantly you could have multiple instances of that shard state without explicit management, saving a lot of complexity and effort.
But closures do. And thus, why closures are a poor man's objects, and objects are a poor man's closures. As an example, Java closures are really anonymous objects with the closed state as instance variables.
> More importantly you could have multiple instances of that shard state without explicit management, saving a lot of complexity and effort.
Technically that's what classes gives you, not objects. But agreed on the sentiment.
If one thinks of them as proxies to the closed-over objects, they are quite like "procedures". Another way to think about them is simply as objects with only a single method.
Also, they can still be "pure functions". Purity is a relation of side effects, not of mechanisms. (Even then, it's a somewhat loose definition -- is allocating memory a side effect?) If you don't allow closures to escape their declared scope, you can handle closed values as extra parameters. So closures don't mean you suddenly can't write pure functions, it means that some input to the function is pre-determined. In other words, closures have the same implications to purity as parameter binding -- absolutely none.
> Even then, it's a somewhat loose definition -- is allocating memory a side effect?
This is leading nowhere. Is loading a value into a register a side effect? If you care.
No, that's what objects give you. Classes are merely one means of creating objects (others exist), but the benefits come from the objects, not their means of construction.
Seriously because unless you can define it, and quantify it then it is just rhetoric.