Closures: why are they so useful?
As an OO developer, maybe I have difficulty seeing its value. What added value do they give? Do they fit in an OO world?
Solution 1:
You can see it as a generalization of a class.
Your class holds some state. It has some member variables that its methods can use.
A closure is simply a more convenient way to give a function access to local state.
Rather than having to create a class which knows about the local variable you want the function to use, you can simply define the function on the spot, and it can implicitly access every variable that is currently visible.
When you define a member method in a traditional OOP language, its closure is "all the members visible in this class".
Languages with "proper" closure support simply generalize this, so a function's closure is "all the variables visible here". If "here" is a class, then you have a traditional class method.
If "here" is inside another function, then you have what functional programmers think of as a closure. Your function can now access anything that was visible in the parent function.
So it's just a generalization, removing the silly restriction that "functions can only be defined inside classes", but keeping the idea that "functions can see whatever variables are visible at the point where they're declared".
Solution 2:
Closures don't give you any extra power.
Anything you can achieve with them you can achieve without them.
But they are very usable for making code more clear and readable. And as we all know clean readable short code is a code that is easier to debug and contains fewer bugs.
Let me give you short Java example of possible usage:
button.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
System.out.println("Pressed");
}
});
Would be replaced (if Java had closures) with:
button.addActionListener( { System.out.println("Pressed"); } );
Solution 3:
For me, the biggest benefit of closures is when you're writing code that starts a task, leaves the task to run, and specifies what should happen when the task is done. Generally the code that runs at the end of the task needs access to the data that's available at the beginning, and closures make this easy.
For example, a common use in JavaScript is to start an HTTP request. Whoever's starting it probably wants to control what happens when the response arrives. So you'll do something like this:
function sendRequest() {
var requestID = "123";
$.ajax('/myUrl', {
success: function(response) {
alert("Request " + requestID + " returned");
}
});
}
Because of JavaScript's closures, the "requestID" variable is captured inside of the success function. This shows how you can write the request and response functions in the same place, and share variables between them. Without closures, you'd need to pass in requestID as an argument, or create an object containing requestID and the function.