what is a closure?

Jeremy Hylton jeremy at alum.mit.edu
Fri Dec 15 12:39:11 EST 2000


In article <8nck3tocsg8kp1u2g1du6nd3lt9gfeckr2 at 4ax.com>,
  Steve Horne <sh at ttsoftware.co.uk> wrote:
> On Thu, 14 Dec 2000 18:09:54 GMT, "Fredrik Lundh" <fredrik at effbot.org>
> wrote:
>
> >In the following example, the "a=a" default argument binding
> >binds add's local name "a" to the value of the "a" argument
> >from make_adder.
> >
> >    def make_adder(a):
> >        def add(b, a=a):
> >            return a + b
> >        return add
> >
> >    >>> m = make_adder(10)
> >    >>> m(20)
> >    30
>
> Are you sure that's a closure? - It looks closer to currying to me.
> And the definition seemed pretty close to the definition of an object
> - a collection of related data and methods.
>
> Currying, in functional languages, is the process of specialising a
> function by specifying one or more of its parameters to produce a
> function with fewer parameters than the original. The notation in
> Python is OK, but not very convenient...
[...]
> I don't claim to be an expert on this. I would simply appreciate it if
> someone could clear up my confusion!

A closure provides a way to resolve free variables in a function body;
it is created when the function is defined. Currying is a way to create
a binding for a formal parameter; it is used when a function is called

The use of default arguments, strictly speaking, isn't really closure
creation and isn't really currying.  It's similar to both.

In Fredrik's example, a=a is rather like a manually created closure.  If
you ignore the a=a part of the parameter list, then a is free in adder.
A closure would provide an environment in which to resolve a.

The use of default arguments in the parameter list works mostly like a
closure.  The one difference is that if a is rebound in make_adder()
after adder() is defined, adder() will still see the old value of a.

Currying occurs when a function is called.  An example using currying
would look something like this:

def make_adder(x):
    def adder(x, y):
        return x + y
    return adder(x)  # returns a function that takes one argument, y
m = make_adder(10)
m(20) == 30

In this example, make_adder() returns a curried function.  The currying
occurs in the call to adder() in the return statement, not during the
definition of adder().  It's interesting to note, though, that default
arguments and currying both cause a formal parameter to be bound to a
value.  They share the property that rebinding the name of the
right-hand side has no effect on the binding in adder().

Incidentally, I am working on a proposal to add real closure creation to
Python 2.1.  I'm working on the implementation and waiting for approval
(or rejection) from the BDFL.  The current text of the proposal is at
    http://python.sourceforge.net/peps/pep-0227.html
Comments are welcome.

-- Jeremy Hylton, <http://www.python.org/~jeremy/>


Sent via Deja.com
http://www.deja.com/



More information about the Python-list mailing list