The Power of Closures

neil's definition of a closure is accurate, but what's missing is the why? Programmers in languages that emphasize closures swear by them. A lot of programmers don't even know what they are, and maybe a larger number understand closures, but don't really understand their utility. Let me propose an expanded definition:

A closure is a function and its environment that can be passed into another function

The important part here is the environment which consists of all variables defined at the scope of the closure creation. The essential functionality is both a form of encapsulation and abstraction. Observe this Ruby example:

def find_birthdays_in_range(min,max)
  birthdays = [ "1970-06-15", "1975-08-13", "1939-03-21", "2001-12-01" ]
  birthdays.find_all { |birthday| birthday > min && birthday < max }
end

So essentially there are 3 functions here that are called from within each other. The third and final one is the closure defined by the ruby block in curly braces, it accepts one parameter called birthday. For easy reference, refer to these function as follows:

A : find_birthdays_in_range
B : find_all
C : anonymous block

Now normally in a lexically-scoped language (almost all of them nowadays) a function can only access parameters passed into it directly. But in this case function C has access to variables defined in function A. That's where the encapsulation comes in, function B never knows anything about min and max. Without closures then function B would have to receive those variables as parameters, and in turn pass them to the anonymous block. But then the generality of function B would be destroyed—it would accept exactly 2 parameters and pass them through to function C. The problem is that those 2 parameters don't really mean anything to find_all. find_all is meant to be able to match members of an array by arbitrary criteria. Function C could just as well reference no variables or 20 variables in determining whether an element of birthdays matches its criteria, and then what?

Without closures it's not really sane to use this structure. Most likely in Java or PHP you would just make find_birthdays_in_range do everything itself. Instead of calling find_all on the array, it would loop through the array itself and gather the matching birthdays manually. There's really nothing wrong with that approach, but you end up writing a lot of the same looping and collecting code over and over. That's where the abstraction comes in. Closures give you the opportunity to write much more general functions.

find_all can find members of an array that match literally any criteria you can express in code, and that's just a relatively basic function that uses closures. You can write any function to call a closure from within, thus generalizing the function. Some examples from the ruby standard library:

  • find lets you specialize what constitutes a match.
  • sort lets you specialize how one object is determined to be greater or less than another object.
  • collect lets you apply an arbitrary transformation to all the members of a collection.
  • gsub lets you make substitutions more complex than a simple regex substitution allows.

In short, closures expand the power of abstraction available to functions.