PEP 309 - Built-in closure type (with tentative syntax proposal)

Carl Banks imbosol at aerojockey.com
Wed Feb 12 19:34:25 EST 2003


Peter Harris wrote:
> My proposal is for a built-in closure type for Python, and
> a syntax for closure literals.
> 
> The reference implementation for the easy part is just:
> 
> class closure(object):
>     __slots__=('fn','args','kw')
>     def __init__(self, fn, *args, **kw):
>         self.fn, self.args, self.kw = (fn, args, kw)
> 
>     def __call__(self, *args, **kw):
>         d = self.kw.copy()
>         d.update(kw)
>         return self.fn(*(self.args + args), **d)
> 
> So you can freeze a function or other callable with a partial
> argument list and keyword arguments into a handy callable
> object.

I hope you're aware that Python (staring from 2.1) already has
closures (and they're quickly becoming my favorite thing ever).  As
others have mentioned, what you're proposing is a built-in curry,
which is just a closure that calls a given function with given
arguments.

In fact, the better way to do the above (2.1+) is to use a real
closure (I'm surprised Martelli didn't point this out):

    from __future__ import nested_scopes

    def curry(fn,*cargs,**ckwargs):
        def call_fn(*fargs,**fkwargs):
            d = ckwargs.copy()
            d.update(fkwargs)
            return fn(*(cargs+fargs),**d)
        return call_fn


> Obviously, the C implementation would try to minimise the
> penalty of a dict copy and update per call, if there's a
> nifty way to do it. If not, it's still a powerful abstraction
> that would be useful even if it's not particularly fast.

I wonder if the biggest benefit of a C-optimized curry would be
eliminating Python function call overhead.  Maybe this could allow
fast functional code when speed matters:

    first = curry(operator.getitem,1)
    first_items = map(first,list_o_lists)

+1 for curry implented in C if this will save a lot over slower Pyhton
methods.


> The kind of things where I see myself using it is in UI callbacks,
> which never get executed in a tight loop anyway (unless something
> is already wrong).

Same here.  Also functional programming for me.


> The syntax proposal is more controversial.

No kidding.  -1 on any syntax change.


> I want a function
> call operator @(*args,**kw) that instead of invoking __call__ on its
> left argument, returns a closure object.
> 
> So the above examples would be written:
> clamp=max@(0)
> buttonmaker=Tkinter.Button@(my_window,bg='white')
> 
> I'm a great fan of concise syntax, and this really appeals to me,
> but what is the community view? Does python need a closure type?
> Is the @ syntax too ugly to be worth it?

I'm a fan of concise code, but not concise syntax.  I would still be
using Perl if I liked concise syntax.

Concerning the semantics: I have two issues.  First, I generally
dislike incomplete solutions, and your proposal is incomplete because
it only allows currying from the left.  Second, there is an
inconsistency between keyword and position arguments: the curried
keyword arguments can be overriden by the caller.  I don't like it,
even if it could be useful.

I would like to be able to curry arbitrary arguments.  Something like:

    curry(fn,__,arg,__)

where the __ parameters become arguments of the curried function.
Functions like curryleft could be special cases or something.


-- 
CARL BANKS




More information about the Python-list mailing list