Epiphany: Closures are Objects, Objects are Closures

Posted by: Clarity Blogs: ASP.NET, on 27 Apr 2009 | View original | Bookmarked: 0 time(s)

I've spent a lot of time over the past few months learning about functional paradigms and the utility of closures therein. Early in my studies, I came across this hacker koan:

The venerable master Qc Na was walking with his student, Anton. Hoping to prompt the master into a discussion, Anton said "Master, I have heard that objects are a very good thing - is this true?" Qc Na looked pityingly at his student and replied, "Foolish pupil - objects are merely a poor man's closures."

Chastised, Anton took his leave from his master and returned to his cell, intent on studying closures. He carefully read the entire "Lambda: The Ultimate..." series of papers and its cousins, and implemented a small Scheme interpreter with a closure-based object system. He learned much, and looked forward to informing his master of his progress.

On his next walk with Qc Na, Anton attempted to impress his master by saying "Master, I have diligently studied the matter, and now understand that objects are truly a poor man's closures." Qc Na responded by hitting Anton with his stick, saying "When will you learn? Closures are a poor man's object." At that moment, Anton became enlightened.

-- Anton van Straaten

At the time, I didn't understand quite what it meant. It came up again recently, and with a better understanding, I think I'm beginning to understand what they mean. First, a little background. If you're not familiar with closures, here's the short version: closures are functions, but they're also a set of variable bindings based on the scope they were defined in. For instance, we can define a function like this:

int number = 5;
Func<int> closure = () => number;

Notice that the lambda we return takes no parameters, but it is still able to make reference to number. We say the lambda has "closed over" the variable, creating a closure. Note that the lambda has a reference to the actual variable in question instead of just taking a snapshot of the variable in time. For example, here's the classic "gotcha":

var closures = new List<Func<int>>();
for (int i = 0; i < 10; i++)
    closures.Add(() => i);
foreach (var closure in closures)

What would you expect this to output? It seems straightforward, but remember that each closure refers directly to i, so we see this result:


We can avoid the problem like this:

for (int i = 0; i < 10; i++)
    int number = i;
    closures.Add(() => number);

This produces the result we actually wanted:


Ok, hopefully we now have a decent understanding of what closures are and how they work. Closures are a powerful tool when used correctly, but they do require some care.

Now, what does this have to do with objects? Objects are a familiar concept to most, but they mean different things to different people. Most languages support their own particular flavor of object-oriented programming, and you pretty much work with what they give you. One concept common to most is encapsulation, the idea of private state inaccessible to other objects. Note that we get this for free with closures: when a closure outlives the scope it's defined in (say, as a return value from a function), no one can touch the variables that have fallen out of scope. Like so:

public static Func<int> CreateClosure()
    int number = 5;
    Func<int> closure = () => number;
    return closure;

When we invoke this function, we get the closure back. number has fallen out of scope, but it persists because our closure has closed over it. In effect, number is private state in our closure. That's kind of cool, but what we really need to make this interesting is some form of method dispatch. This is another common construct in OOP: the idea that objects expose some interface for controlled interactions with private state. Since our object is a function, we only have one point of entry. But if we make that entry point a function that dispatches functions based on messages passed in, we can do some interesting things. Let's see if we can hack something together:

public static Func<string, string> CreateClosure
    (Dictionary<string, Func<string[], string>> methods)
    return message =>
        string[] methodWithParams = message.Split(new[] { ' ' });
        string methodName = methodWithParams[0];
        string[] withParams = methodWithParams.Skip(1).ToArray();
        if (!methods.ContainsKey(methodName))
            return "message not understood!";
        return methods[methodName](withParams);

The string manipulation code is a pretty ugly, but the premise is simple. First, we accept a dictionary of methods as a parameter. This will hold the public functions that our closure will respond to. Then we define and return our actual closure. This is just a function that receives a message as a string and dispatches the appropriate function. For a trivial (but instructive!) example, we'll use this pattern to create a representation of a pez dispenser.

<p>Let's add some private state and a few methods:<pre class=public static Func<string, string> PezDispenserInit(string name) { int count = 0; var methods = new Dictionary<string, Func<string[], string>>(); methods["describe"] = parameters => { return string.Format("my favorite {0} pez dispenser - it has {1} pez left", name, count); }; methods["dispense"] = parameters => { if (count > 0) { count--; return string.Format("a delicious pez! {0} has {1} pez left", name, count); } else { return string.Format("{0} is out of pez . . .", name); } }; methods["add"] = parameters => { int add = int.Parse(parameters[0]); count += add; return string.Format("added {0} to {1}! now {1} has {2} pez!", add, name, count); }; return CreateClosure(methods); }

We've added private data (name and count) and a few methods to call based on messages. Note that each of our public methods is also a closure; the public methods close over our private state, and our method dispatcher closes over the dictionary of methods. To keep things simple, I've adopted the convention that each method takes an array of strings as a parameter and returns a string. The methods themselves are all pretty self-explanatory, so I won't go into detail. Now, let's add a little code to create a simple command line interpreter:

static void Main(string[] args)
    var closures = new Dictionary<string, Func<string, string>>();
    while (true)
        Console.Write("> ");
        string[] line = Console.ReadLine().Split(new[] { '.' });
        string name = line[0];
        string message = line[1];
        string result;
        if (message == "init")
            closures[name] = PezDispenserInit(name);
            result = name + " initialized";
            result = closures[name](message);

We have a dictionary for our closure objects allowing us to specify them by name and pass a message. We handle the init message explicitly to create new closures. Kind of a kludge, but this is just an example. Otherwise, we just forward messages onto the appropriate closures. Let's try it out:


Pretty cool. Notice that each object maintains its own internal state separate from the other. But is this really useful? All we've really gained is stuff that's built into C#'s type system. What it really gives us is total flexibility. For example, C#'s type system is designed for class-based inheritance (as are many mainstream languages). This is useful in some domains (UI programming, for example), but I don't think it's a great fit in a lot of scenarios. If I wanted to use prototypal inheritance (Steve Yegge has written extensively about this) instead, I'm sort of out of luck. But if I can define my own object system via closures, it's actually pretty simple (look for a future blog post on this).

To close, let's go back to the original point. Objects are a poor man's closures: closures give you complete flexibility to suit your solution to the domain. But the reverse is also true; closures are a poor man's objects. Objects have a slew of advantages over closures because the language (whatever language you're using) is built with its own type system in mind. Even if it's not an ideal model for the problem, the out-of-the-box solution is almost always going to be the correct one for reasons of readability, maintainability, performance, etc. So keep these techniques in mind, but use them very sparingly.

Hope this helps.

Category: C# | Other Posts: View all posts by this blogger | Report as irrelevant | View bloggers stats | Views: 3562 | Hits: 28

Similar Posts

  • The "Error creating window handle" exception and the Desktop Heap more
  • Identity Maps more
  • Overloading Entity Framework Methods: More GetObjectStateEntries more
  • Introducing the SmartBag for ASP.NET MVC. . . and soliciting feedback more
  • Calling web services with structured parameters from JavaScript more
  • Entity Framework object graphs and viewstate more
  • Object Thinking Domain Model Example more
  • OBJECT_NAME enhancement and OBJECT_SCHEMA_NAME addition in SQL Server 2005 SP2 more
  • TSql vs. SQL CLR Performance Analysis more
  • New Developer Community at Business Objects more

News Categories

.NET | Agile | Ajax | Architecture | ASP.NET | BizTalk | C# | Certification | Data | DataGrid | DataSet | Debugger | DotNetNuke | Events | GridView | IIS | Indigo | JavaScript | Mobile | Mono | Patterns and Practices | Performance | Podcast | Refactor | Regex | Security | Sharepoint | Silverlight | Smart Client Applications | Software | SQL | VB.NET | Visual Studio | W3 | WCF | WinFx | WPF | WSE | XAML | XLinq | XML | XSD