The main intentional difference in semantics between the mainstream languages is whether to allow changes to variables captured by the closure. Java and Python say no, the other languages say yes (well, I don't know Objective C, but the rest do). The advantage to being able to change variables is that you can write code like this:
public static Func<int,int> adderGen(int start) {
return (delegate (int i) { // <-- start is captured by the closure
start += i; // <-- and modified each time it's called
return start;
});
}
// later ...
var counter = adderGen(0);
Console.WriteLine(counter(1)); // <-- prints 1
Console.WriteLine(counter(1)); // <-- prints 2
// :
// :
You'll notice that this is a lot less code than the equivalent counter class, although C# (the language used here) generates exactly that code for you behind the scenes.
The downside is that captured variables really are shared, so if you generate a bunch of adders in a classic for loop you are in for a surprise...
var adders = new List<Func<int,int>>();
for(int start = 0; start < 5; start++) {
adders.Add(delegate (int i) {
start += i;
return start;
});
}
Console.WriteLine(adders[0](1)); // <-- prints 6, not 1
Console.WriteLine(adders[4](1)); // <-- prints 7, not 5
Not only is start
is shared across all 5 closures, the repeated start++
gives it the value 5 at the end of the for loop. In a mixed paradigm language, my opinion is that Java and Python have the right idea--if you want to mutate captured variables, you're better off being forced to make a class instead, which makes the capture process explicit, when you pass them to the constructor, for example. I like to keep closures for functional programming.
By the way, Perl has closures too.