To my knowledge, combined with the knowledge of others, among the mainstream languages
have closures and anonymous functions. Plain C/C++ doesn't have either of those.
Do closures in these languages have the same semantics? How important are they for everyday programming?
Some background: I've been reading about the new additions to Objective C that target Apple's Grand Central Dispatch and thought I should learn whether there is really only one or different ways to introduce block-like structures into the language.
A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function's scope from an inner function.
Languages which support closure (such as JavaScript, Swift, and Ruby) will allow you to keep a reference to a scope (including its parent scopes), even after the block in which those variables were declared has finished executing, provided you keep a reference to that block or function somewhere.
This is called a JavaScript closure. It makes it possible for a function to have "private" variables. The counter is protected by the scope of the anonymous function, and can only be changed using the add function. A closure is a function having access to the parent scope, even after the parent function has closed.
Closures are frequently used in JavaScript for object data privacy, in event handlers and callback functions, and in partial applications, currying, and other functional programming patterns.
Please clarify your question: What do you mean with work? How you use them, when they are used or how they are implemented internally?
The process of compilation of the .NET-languages (VB/C#) can show you how closures can be generally represented:
The closure is translated into an anonymous class with fields for the enclosed variables. The function pointer (delegate) to access the closure is nothing but a pointer on a special method implemented by the anonymous class.
Some notes on the importance of closures:
.NET: Not that much explicit usage of closures. Anonymous functions are sometimes used for events and functional representation of data. Main use is the (internal) representation of LINQ-queries.
Python:
Poor support for anonymous functions - only lambda vars: expr
- syntax.
Javascript: The whole function syntax is nothing but syntactic sugar around anonymous functions and closures!
function f(x) { return x + 1; }
equals
var f = function(x) { return x + 1; }
Ruby: Heavy use of closures: Most program flow structures rely on them. See
array.each do |x|
# code
end
is nothing but a call of the array#each
function with an anonymous function to be executed (block) passed as an argument. Representation in C#:
Array.Each(x => {
// Code
})
Generally, a closure is something like this:
# Enclose `i` - Return function pointer
def counter():
i = 0
def incr():
i += 1
print(i)
return incr
c = counter()
c() # -> 1
c() # -> 2
c() # -> 3
All the languages (except Java - You have anonymous classes, not functions!) you enumerated will allow things like this.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With