Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between closures and traditional classes?

What are the pros and cons of closures against classes, and vice versa?

Edit:
As user Faisal put it, both closures and classes can be used to "describe an entity that maintains and manipulates state", so closures provide a way to program in an object oriented way using functional languages. Like most programmers, I'm more familiar with classes.

The intention of this question is not to open another flame war about which programming paradigm is better, or if closures and classes are fully equivalent, or poor man's one-another.

What I'd like to know is if anyone found a scenario in which one approach really beats the other, and why.

like image 792
Sebastián Grignoli Avatar asked Jul 30 '10 04:07

Sebastián Grignoli


3 Answers

Functionally, closures and objects are equivalent. A closure can emulate an object and vice versa. So which one you use is a matter of syntactic convenience, or which one your programming language can best handle.

In C++ closures are not syntactically available, so you are forced to go with "functors", which are objects that override operator() and may be called in a way that looks like a function call.

In Java you don't even have functors, so you get things like the Visitor pattern, which would just be a higher order function in a language that supports closures.

In standard Scheme you don't have objects, so sometimes you end up implementing them by writing a closure with a dispatch function, executing different sub-closures depending on the incoming parameters.

In a language like Python, the syntax of which has both functors and closures, it's basically a matter of taste and which you feel is the better way to express what you are doing.

Personally, I would say that in any language that has syntax for both, closures are a much more clear and clean way to express objects with a single method. And vice versa, if your closure starts handling dispatch to sub-closures based on the incoming parameters, you should probably be using an object instead.

like image 118
clacke Avatar answered Oct 21 '22 23:10

clacke


Personally, I think it's a matter of using the right tool for the job...more specifically, of properly communicating your intent.

If you want to explicitly show that all your objects share a common definition and want strong type-checking of such, you probably want to use a class. The disadvantage of not being able to alter the structure of your class at runtime is actually a strength in this case, since you know exactly what you're dealing with.

If instead you want to create a heterogeneous collection of "objects" (i.e. state represented as variables closed under some function w/inner functions to manipulate that data), you might be better off creating a closure. In this case, there's no real guarantee about the structure of the object you end up with, but you get all the flexibility of defining it exactly as you like at runtime.

Thank you for asking, actually; I'd responded with a sort of knee-jerk "classes and closures are totally different!" attitude at first, but with some research I realize the problem isn't nearly as cut-and-dry as I'd thought.

like image 35
Faisal Avatar answered Oct 21 '22 23:10

Faisal


Closures are very lightly related to classes. Classes let you define fields and methods, and closures hold information about local variables from a function call. There is no possible comparison of the two in a language-agnostic manner: they don't serve the same purpose at all. Besides, closures are much more related to functional programming than to object-oriented programming.

For instance, look at the following C# code:

static void Main(String[] args)
{
    int i = 4;
    var myDelegate = delegate()
    {
        i = 5;
    }

    Console.WriteLine(i);
    myDelegate();
    Console.WriteLine(i);
}

This gives "4" then "5". myDelegate, being a delegate, is a closure and knows about all the variables currently used by the function. Therefore, when I call it, it is allowed to change the value of i inside the "parent" function. This would not be permitted for a normal function.

Classes, if you know what they are, are completely different.

A possible reason of your confusion is that when a language has no language support for closures, it's possible to simulate them using classes that will hold every variable we need to keep around. For instance, we could rewrite the above code like this:

class MainClosure()
{
    public int i;

    void Apply()
    {
        i = 5;
    }
}

static void Main(String[] args)
{
    MainClosure closure;
    closure.i = 4;

    Console.WriteLine(closure.i);
    closure.Apply();
    Console.WriteLine(closure.i);
}

We've transformed the delegate to a class that we've called MainClosure. Instead of creating the variable i inside the Main function, we've created a MainClosure object, that has an i field. This is the one we'll use. Also, we've built the code the function executes inside an instance method, instead of inside the method.

As you can see, even though this was an easy example (only one variable), it is considerably more work. In a context where you want closures, using objects is a poor solution. However, classes are not only useful for creating closures, and their usual purpose is usually far different.

like image 1
zneak Avatar answered Oct 22 '22 01:10

zneak