views:

431

answers:

4

To my knowledge, combined with the knowledge of others, among the mainstream languages

  • Objective C
  • C#
  • VB.net
  • Java
  • Python
  • Ruby
  • Javascript
  • Lisp
  • Perl

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.

+5  A: 

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.

Dario
Well, to be more specific about Python, closures are completely supported, but anonymous functions are indeed limited to `expressions`, not `statements`.
ilya n.
BTW, the example for Python needs `nonlocal i` before `i+=1`. This is because of the way variables work in Python: in `incr()` variable `i` is changed, therefore (in the absence of `global` or `nonlocal`) Python assumes it must be local, which means it's undefined.
ilya n.
That's one of the few things I dislike about Python...
Fernando
A: 

Java does not have closures or anonymous functions, although it does have anonymous classes that can be used to simulate these to some extent.

There were competing proposals to have closures added to the language in the next version of Java, but none of these have not been included in the list of official changes.

Ken Liu
+2  A: 

Java excluded the closures in their design, basically ( and although it may sound contradictory now ) because they wanted to keep the language simple in many aspects.

Since day 1 v1.1 however, Java have supported the same functionality, but instead of mixing paradigms ( functional vs. OO ) they allowed the existence of anonymous inner classes which pretty much serve for the same purpose. Since they are not closures but classes you have to type a few more characters.

So for instance to have a Timer which receives a TimerTask as block to be executed you would write:

 Timer timer = new Timer();

 timer.schedule( new TimerTask() {  // this is like the code block. 
     public void run() {
          System.out.println("Hey!");
     }
 },0);

As you see the "TimerTask() { ... " is the definition for the anonymous inner class. That instance could be assigned also to a variable an passed as argument.

TimerTask task = new TimerTask() {
     public void run() {
     }
 };


....
timer.schedule( task , 0 ) ;

You can have this kinds of constructs, but they are not closures.

Closures are still on debate to be added to the Java programming language.

Here's an interesting talk by Joshua Bloch: "The closures controversy"

Here is an article on "Principles for Evolving the Java Language"

OscarRyz
"Java excluded the closures ...because they wanted to keep the language simple". I'm sorry, but... did you just go there?
RHSeeger
+1  A: 

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.

Nathan Sanders
Actually, now Python allows this with `global` and `nonlocal` statements.
ilya n.
Oh, right, I forgot. I used Python 2.x for too long compared to Python 3.x.
Nathan Sanders