Self-currying functions
Dave Benjamin
ramen at lackingtalent.com
Fri May 23 02:14:47 EDT 2003
In article <qsGya.27509$XV1.109 at nwrdny03.gnilink.net>, Carl Banks wrote:
> Dave Benjamin wrote:
>> The above nested lambda expression is what curried() creates and then
>> eval's. I'd like to do this without the need for an eval, but I am having
>> trouble building a for-loop to accomplish this.
>
> Ah, there you go. You're thinking iteratively when you should be
> thinking recursively.
>
> What I did in my solution was to simply look at it this way: you want
> to return a function that checks the number of args. If there are
> enough, call it; otherwise, curry the function, and then recursively
> call the self-curry-maker on the curried function.
Beautiful. Now can you make it look like an airplane? ;)
Thanks for the wise words and speedy response!
The following is my response, adapted from your example to support Alex
Martelli's curry function (and as a result, curried named parameters). I'm
starting to find interesting uses I hadn't anticipated. Very grateful for
your help.
Peace,
Dave
# selfcurry.py
'''
>>> f = selfcurry(lambda w, x, *y, **z: (w, x, y, z))
>>> f(1, 3)
(1, 3, (), {})
>>> f(1)(3)
(1, 3, (), {})
>>> f(1)(2, 3)
(1, 2, (3,), {})
>>> f(1, a=5)(2, 3)
(1, 2, (3,), {'a': 5})
>>> f(1, a=5)(2, 3, b=6)
(1, 2, (3,), {'a': 5, 'b': 6})
'''
from __future__ import nested_scopes
def curry(func, *create_time_args, **create_time_kwds):
"""
Binds arguments to a function.
Author: Alex Martelli
Source: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52549
"""
def curried_function(*call_time_args, **call_time_kwds):
args = create_time_args + call_time_args
kwds = create_time_kwds.copy()
kwds.update(call_time_kwds)
return func(*args, **kwds)
return curried_function
def selfcurry(func, nargs=None):
"""
Returns a function that curries itself.
Authors: Carl Banks, Dave Benjamin
Source: http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&frame=right&th=736757dcaeb50c2e#link2
"""
if nargs is None:
nargs = func.func_code.co_argcount
def call_if_enough_args(*args, **kwds):
if len(args) < nargs:
return selfcurry(curry(func, *args, **kwds), nargs - len(args))
else:
return func(*args, **kwds)
return call_if_enough_args
More information about the Python-list
mailing list