What is a closure?

Closures have been around a long time yet have experienced a resurgence in the last decade. They were first implemented in the functional language Scheme then later introduced to object-oriented programming in Smalltalk. The ideas behind closures can be found in Java anonymous classes, C++ lambdas, Python nested functions, Ruby procs, Eiffel agents, and more. Closures are now supported in one form or another by many programming languages (C is a notable exception) but remain somewhat mysterious and are often not fully understood. Closures have major implications for how we program and also require significant effort behind the scenes to properly support them. Like any fundamental concept, it’s important for you, as a programmer, to know how they work.

In this article I will explain some basics. First I will work through a simple example, in case you are new to closures. Then I will show how the same semantics can be implemented without using closures.

A basic example

A closure is basically just a nested function which accesses variables from its parent scope. To demonstrate this we’ll start with a very simple example of a closure. I’ve used a pseudo-syntax based on my Cloverleaf project since I think it conveys the intent clearly. Look at the code first and then I will explain it a bit more. Don’t worry if you are new to closures and don’t quite understand. You may choose to skip ahead to how they are implemented and then come back to this section; understanding the mechanics actually makes matters clearer.

typedef int_function = () -> ( : integer );

function create_closure = ( x : integer ) -> ( : int_function )
{
	function square = () -> ( : integer )
	{
		return x*x;
	};

	return square;
};

var close_foo = create_closure(4);
var close_bar = create_closure(8);

print( close_foo() ); //prints 16
print( close_bar() ); //prints 64

Now let’s go over some of this code:

typedef int_function = () -> ( : integer );

The typedef ‘int_function’ defines a function type taking no parameters and returning an integer. I am just using the typedef here to make the next line in the code clearer.

function create_closure = ( x : integer ) -> ( : int_function)

You may not be familiar with the ‘=’ assignment being used to assign a block of code to a function name. We are not calling the ‘create_closure’ function at this point. First we create an anonymous function block and assign it to the variable ‘create_closure’. We can then use this variable to call the function. This is a concept known as first-class functions: functions themselves are treated like any other variable and can be assigned, returned, and passed as parameters.

var close_foo = create_closure(4);

Here we actually call ‘create_closure’ which returns a so-called “closure”. Let’s take another look at the body of the ‘create_closure’ function:

	function square = () -> ( : integer )
	{
		return x*x;
	};

	return square;

Inside the ‘create_closure’ function, we define another function, ‘square’. Furthermore this inner function uses the parameter ‘x’ passed into its “parent”. What happens when ‘create_closure’ returns? Even though the variable ‘x’ goes out of scope, its value at the time ‘create_closure’ is called is captured behind the scenes along with the ‘square’ function itself. That’s what makes ‘square’ a closure and not just a straightforward reference to a function.

print( close_foo() );

Because the closure that is returned from ‘create_closure’ keeps track of its “lexical scope” (the value of ‘x’ in this case), the call to ‘close_foo’ will print the value 16 (and calling ‘close_bar’ will print 64).

What really happens

To understand how this works I’ll show the same code written in an object-oriented pseudo code. Basically we will build a construct called a function object. It comprises an interface, an implementation, and a factory function (‘create_closure’).

interface int_function
{
	int call();
}

class square implements int_function
{
	int value;
	int call()
	{
		return value*value;
	}
}

int_function create_closure( int value )
{
	square c = new square();
	c.value = value;
	return c;
}

int_function close_foo = create_closure(4);
int_function close_bar = create_closure(8);

print( close_foo.call() );
print( close_bar.call() );

When written this way we can see that a closure is quite simple. Instead of defining an inner function, we instantiate an object, ‘square’. To mimic the closure’s ability to capture ‘value’ from the outer function’s scope, we copy it explicitly into the object. Finally, we return this object rather than the inner function in the previous example.

Using an interface is an important part of the concept here. The caller to ‘create_closure’ doesn’t care what instance it gets, so long as it obeys the ‘int_func’ interface. ‘create_closure’ could return any class, or a different class to each caller. In the previous version of the code, we actually only see this abstract type: the concrete function is anonymous and private to the ‘create_closure’ function.

By value or reference

In the object-oriented code above it is clear we have “captured” the variable ‘value’ by value. That is, we’ve made a separate copy of it. Another option is to capture it by reference. That is, what if our object, standing in for a closure, took a reference instead of copying? The example we’ve used so far is a bit too simple to show the difference so let’s create a new one (using a bit of C++ notation for the references).

class incrementer implements int_func //int_func remains the same as in our previous example
{
   int & counter; //a C++ style reference
   incrementer( int & start ) //constructor initializes counter
       : counter(start)
   { }

   int call()
   {
       return ++counter;
   }
}

int_func create_incrementer( int & start_count)
{
   incrementer c( start_count );
   return c;
}

int x = 10;
int_func foo_incrementer = create_incrementer(x);
int_func bar_incrementer = create_incrementer(x);

print( foo_incrementer.call() ); //prints 11
print( bar_incrementer.call() ); //prints 12
print( foo_incrementer.call() ); //prints 13

This example is similar to the one before it. The key difference is that instead of making a copy, we use a reference. While we have created two instances of the ‘incrementer’ class, they both refer to the same variable ‘x’. That’s why the sequence of calls results in the sequence 11,12,13 rather than 11,11,12 (which would happen if a copy of ‘x’ was taken).

When the designer of a language chooses to implement closures, they must decide how to handle this question of handling them by reference or by value. It varies greatly among current languages.

In C++, when creating a lambda (that is, a closure), you the programmer can specify whether variables from an outer scope will be copied directly (by value) or pointed to indirectly (by reference). However, as C++ requires manual memory control, you have to be careful when using references: after calling a function that returns a lambda, those variables captured by reference could be out of scope!

In JavaScript, at a logical level, you actually have a scope chain. The entire containing scope is kept, which is essentially the same as capturing all variables by reference.

In a functional language like Haskell, where most data is immutable, there is no distinction between “by value” or “by reference”. Since an immutable never changes, whatever value it has when the closure is created will be retained at the time it is executed.

In Java, anonymous inner classes must have all parameters to functions passed in with the ‘final’ keyword. This basically insures that you won’t manipulate those variables directly. It’s a bit confusing as to whether this is by value or reference; since objects are treated implicitly like pointers, copying a value is actually taking a reference.

Closing off

The examples I’ve provided here are quite simple. They don’t get into any complex data relations, but rest assured the same basic implementation can be used for all closures.

What isn’t shown is the memory management aspect. Finding a system which keeps closures safe, yet efficient, is an ongoing field of investigation. There are also many ways to optimize closures, some of which can completely erase the closure in the generated executable. What a compiler produces, or VM executes, could vary significantly from my example.

The concept however remains the same: a closure is an implicit creation of a data object attached to a function.

10 Comments

  1. levinv

    Referring to the object as a “function object” in the second code sample isn’t quite correct. Function objects are instances of classes that can actually be called as functions directly. In the code sample you still have to execute the ‘call’ member function explicitly.

    Since a language has to have support for function objects, they can be considered as an intermediate form toward supporting closures fully.

    1. mortoray

      I am refering mainly to a function pattern object: the instantiated class is used like a function. In my original version I used the C++ operator() overload to make it actually directly callable, but I thought that might be confusing to those not familiar with C++. Showing the “call” function makes it clear, but still maintains the pattern.

  2. Andrzej Krzemieński

    This is a very nice introduction to closures. Thanks! I wanted to share a couple of thoughts that your article inspired.

    “first-class functions: functions themselves are treated like any other variable and can be assigned, returned, and passed as parameters”

    — I may be wrong, but I thought in pure functional languages like Haskell functions are ‘first-class citizens’ also because they are comparable. In functional languages it is possible (or am I wrong?) to check whether two functions are equal, meaning: they return equal values for equal inputs. This is not verifiable in imperative languages, therefore function objects are never first-class citizens due to this lack of equality-comparison.

    “In JavaScript, […] capturing all variables by reference.”

    — this is besides your point, but it is worth noting tat implicit capturing in closures works differently than explicit passing of arguments to functions in JavaScript. I.e., built-in types are captured as-if by reference, but are passed to functions by value. This may be very confusing.

    “In Java, […] since objects are treated implicitly like pointers, copying a value is actually taking a reference.”

    — Passing pointer to object by value (as in Java) is not same as passing the object by reference. This article by Scott Stanchfield explains the subtle difference.

    Regards,
    &rzej

    1. mortoray

      My description of first-class functions here is very short indeed. I suppose one could go more into depth on that topic. That they are not comparable in imperative languages is unfortunate. If we look at how I implemented this closure it would actually be quite easy to check if two instances of it would return the same value (simply implement a virtual compare operator). Now, I suspect being comparable is truly limited to the same instance, not that unrelated closures could compare (that would be quite a feet).

      I agree that JavaScript is at first confusing, but it makes sense. In my own language I will probably do all capturing by reference and all parameter passing by value (at least by default). It makes the most sense.

      In my article about names/references I note that in C++ it is incorrect to consider references as distinct from pointers (despite what the standard likes to claim). As in C++, Java objects are essentially pointers, as the article claims. But I maintain that passing a pointer by value is the exact same as passing an object by reference. We have to be very clear on separating the name from the value, and I think Scott’s article confuses this as well. Consider that since objects in Java are mutable, you can implement swap functions which will work (just not in a generic fashion).
      https://mortoray.com/2012/01/08/whats-an-object-whats-a-variable/

    2. Andrzej Krzemieński

      “But I maintain that passing a pointer by value is the exact same as passing an object by reference. We have to be very clear on separating the name from the value, and I think Scott’s article confuses this as well. “

      I do not think Scott is confusing things. It looks more to me that you can define “pass by reference” in a number of (incompatible) ways. If you define “pass by reference” as not copying the entire value but only “some handle”, then your claim that “passing a pointer by value is the exact same as passing an object by reference” is certainly true.

      Another interpretation is depicted by this test (similar Scott’s example):

      public void fun()
      { 
        Dog dog1= new Dog("Max");
        Dog dog2= dog1;
        dog1= new Dog("Fifi");  // (1)
        // dog1 is "Fifi", dog2 is "Max"
      }
      

      Now given the following refactoring:

      public void fun()
      { 
        Dog dog1= new Dog("Max");
        Dog dog2= dog1;
        makeFifi(dog1); // ??
        // dog1 is "Fifi", dog2 is "Max"
      }
      

      Is it possible to implement function makeFifi so that using it in place of line (1) does not change semantics of function fun? In C++ it is possible if you pass pointer by reference!

      Regards,
      &rzej

    3. mortoray

      In C++ this is only possible if you use a pointer type, say “Dog *” instead of just “Dog”. Otherwise you won’t be replacing the pointer, but instead copying a new value to instance “dog1” (presumably not the intended semantics). This is an important distinction since in Java you can also easily overwrite the data in “dog1” with the “makeFifi” function.

      If you do wish to replace the pointer then you’ll actually have to pass a “Dog*” to the makeFifi function which will need to accept a “Dog*&” parameter. A simple “Dog&” parameter will not be able to replace the caller’s value for “dog1”. So your variable has to be “Dog * dog1”.

      But you’re no longer taking a reference to the dog object anymore, you’re taking a reference to the pointer to the object. A similar affect can actually be achieved with Java if you put your Objects into an array of length [1]. So in Java you can get this to work with minimal syntax changes (just as you need syntax changes in C++).

  3. Andrzej Krzemieński

    I wanted to reply to your last reply, but since the site does not allow this level of nesting I am just sending another comment — sorry for the confusion.

    “In C++ this is only possible if you use a pointer type, say »Dog *« instead of just »Dog«.”

    — I agree that “this” is “only” observable for pointers in C++. However, let me point out that using pointers like this is no hack or academic example. It is a natural usage if you choose to program in OO manner: where you “install” objects somewhere in the global address space; functions and scopes come and go; and your objects still exist and send signals to one another. I would probably not use raw pointers but something that lets me manage memory:

    void fun()
    {
      shared_ptr<Animal> dog1{ new Dog("Max") };
      shared_ptr<Animal> dog2 = dog1;
      makeFifi(dog1); // (1)
      // dog1 is "Fifi", dog2 is "Max"
    }
    

    This is a normal way of programming. (At least I think it is — I am not found of OO style). I can make this work because I am passing the pointer by reference. Note that it is not a a pointer to pointer, or a handle to pointer. The subtle difference is in some special semantics of references: they are not required to have storage, pointers or references to references are disallowed, they extend the life-time of temporaries they bind to…

    The hack with length-1 array, while it works, is a hack: a workaround for missing full pass-by-reference semantics (if anyone misses it). (Would I be wrong to say that many Java programmers would be confused to see such array?)

    I agree that pass-by-pointer is to great extent similar to pass-by-reference semantics, but the difference we are discussing makes it more “partial pass-by-reference”.

    Regards,
    &rzej

    1. mortoray

      Though a shared_ptr is more like a pointer to a pointer… ;)

      But I digress. I think our little exchange, and Scott’s article, show that seemingly simple ideas like “Pass by value/reference” are perhaps simplifying the issue too much. To understand them requires you understanding exactly what your variables represent.

      C++ references are in any case a fairly unique language feature. I don’t think they are correctly named however. I actually want to write an article just about this feature.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s